首页 > 其他分享 >NordicOI 2023

NordicOI 2023

时间:2024-10-18 10:32:59浏览次数:6  
标签:NordicOI ve int sum MAXN vec 2023 using

A. ChatNOI

题目描述

给定一个由 \(N\) 个小写英文单词组成的文章,我们定义一个 \(k+1\) 个单词的可能性为其在文章中的出现次数。现在给出一个句子的前 \(k\) 个单词,你要补全后面的 \(m\) 个单词,使得其中所有长度为 \(k+1\) 的字串的可能性最小值最大。有 \(Q\) 次询问。

思路

因为我们是不断在后面加入单词,所以我们可以把这个文章变成一个图。每个的字串 \([l,l+k-1]\) 连向 \([l+1,l+k]\),边权为 \([l+1,l+k]\) 的可能性。在这个图上我们要找到一个长度为 \(m\) 的路径使得其边权最小值最大。

这里很显然点,边和边权总和的数量级都是 \(O(N)\) 的,而不同的边权数量是 \(O(\sqrt N)\) 的,因为最优情况下边权依次是 \(1,2,\dots,\sqrt N\)。

这个有什么用呢?我们可以暴力从大到小枚举每种边权 \(x\),并把所有 \(\ge x\) 的边加入。令 \(u\) 为询问给出的句子对应的点,如果此时第一次从 \(u\) 开始可以行走至少 \(m\) 步,那么这个询问的答案为 \(x\),使用拓扑排序解决。

空间复杂度 \(O(N+Q)\),时间复杂度 \(O((N+Q)\sqrt N)\)。

代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;

const int MAXN = 500001, MAXQ = 100001, INF = INT_MAX;
const ll b[2] = {29, int(1e9) + 9}, MOD = int(1e9) + 7;

struct query {
  int m, id;
  ull x;
}a[MAXQ];

int n, k, tot, q, in[MAXN], dp[MAXN], f[MAXN], fid[MAXN];
ull sum[MAXN], Pow[MAXN];
string S[MAXN];
map<ull, int> mp, cnt;
vector<tuple<int, int, int>> e[MAXN];
vector<int> ve, ans[MAXQ];
vector<tuple<int, int, int, int>> vec;

int Hash(const string &s) {
  int ret = 0;
  for(char c : s) {
    ret = (1ll * ret * b[0] % MOD + c - 'a' + 1) % MOD;
  }
  return ret;
}

ull Calc(int l, int r) {
  return sum[r] - sum[l - 1] * Pow[r - l + 1];
}

void topo_sort() {
  queue<int> que;
  fill(in + 1, in + tot + 1, 0);
  for(int i = 1; i <= tot; ++i) {
    dp[i] = 0;
    for(auto [v, w, id] : e[i]) {
      in[v]++;
    }
  }
  for(int i = 1; i <= tot; ++i) {
    if(!in[i]) {
      que.push(i);
    }
  }
  for(; !que.empty(); ) {
    int u = que.front();
    que.pop();
    for(auto [v, w, id] : e[u]) {
      if(dp[u] + 1 > dp[v]) {
        dp[v] = dp[u] + 1, f[v] = u, fid[v] = id;
      }
      if(!(--in[v])) {
        que.push(v);
      }
    }
  }
  for(int i = 1; i <= tot; ++i) {
    if(in[i]) {
      dp[i] = INF;
      for(auto [v, w, id] : e[i]) {
        if(in[v]) {
          f[v] = i, fid[v] = id;
        }
      }
    }
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> k;
  Pow[0] = 1;
  for(int i = 1; i <= n; ++i) {
    string s;
    cin >> s;
    S[i] = s;
    sum[i] = sum[i - 1] * b[1] + Hash(s);
    Pow[i] = Pow[i - 1] * b[1];
  }
  for(int i = 1; i <= n - k; ++i) {
    cnt[Calc(i, i + k)]++;
  }
  for(int i = 1; i <= n - k + 1; ++i) {
    ull h = Calc(i, i + k - 1);
    if(!mp.count(h)) {
      mp[h] = ++tot;
    }
    if(i > 1) {
      vec.emplace_back(cnt[Calc(i - 1, i + k - 1)], mp[Calc(i - 1, i + k - 2)], mp[h], i + k - 1);
      ve.emplace_back(cnt[Calc(i - 1, i + k - 1)]);
    }
  }
  cin >> q;
  for(int i = 1; i <= q; ++i) {
    cin >> a[i].m;
    for(int j = 1; j <= k; ++j) {
      string s;
      cin >> s;
      a[i].x = a[i].x * b[1] + Hash(s);
    }
    a[i].x = mp[a[i].x];
  }
  sort(ve.begin(), ve.end()), ve.erase(unique(ve.begin(), ve.end()), ve.end()), reverse(ve.begin(), ve.end());
  sort(vec.begin(), vec.end(), greater<tuple<int, int, int, int>>());
  int j = 0;
  for(int x : ve) {
    for(; j < int(vec.size()); ++j) {
      auto [w, u, v, id] = vec[j];
      if(w >= x) {
        e[v].emplace_back(u, w, id);
      }else {
        break;
      }
    }
    topo_sort();
    for(int i = 1; i <= q; ++i) {
      if(!a[i].x || ans[i].size() || dp[a[i].x] < a[i].m) {
        continue;
      }
      int u = a[i].x, cnt = 1;
      for(; cnt <= a[i].m; u = f[u], cnt++) {
        ans[i].emplace_back(fid[u]);
      }
    }
  }
  for(int i = 1; i <= q; ++i) {
    if(ans[i].empty()) {
      for(int j = 1; j <= a[i].m; ++j) {
        cout << S[1] << " \n"[j == a[i].m];
      }
    }else {
      for(int x : ans[i]) {
        cout << S[x] << " ";
      }
      cout << "\n";
    }
  }
  return 0;
}

B. Ice Cream Machines

题目描述

有 \(N\) 个人,第 \(i\) 个人想吃第 \(c_i\) 种口味的冰淇淋。有 \(k\) 个冰淇淋机,每种机器都可以制作任意口味的冰淇淋,但是每次让一个冰淇淋机制作和之前不同的冰淇凌都要清洗一次。第一次使用也要清洗。

求至少要清洗几次。

思路

用贪心解决。我们用 set 记录每个冰淇凌机当前是什么冰淇凌,该冰淇凌下次出现的位置,我们肯定会选择下次出现位置更靠后的清洗。

空间复杂度 \(O(N)\),时间复杂度 \(O(N\log N)\)。

代码

#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;

const int MAXN = 200001, MAXM = 200001, MAXK = 200001;

int n, m, k, c[MAXN], cnt[MAXM], a[MAXK], pos[MAXM], ans;
set<pii, greater<pii>> s;
vector<int> ve[MAXM];

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m >> k;
  for(int i = 1; i <= n; ++i) {
    cin >> c[i];
    ve[c[i]].emplace_back(i);
  }
  for(int i = 1; i <= m; ++i) {
    ve[i].emplace_back(n + 1);
  }
  for(int i = 1; i <= k; ++i) {
    s.insert({n + 1, i});
  }
  for(int i = 1; i <= n; ++i) {
    if(!pos[c[i]]) {
      ans++;
      auto [cur, p] = *s.begin();
      s.erase(s.begin());
      s.insert({*upper_bound(ve[c[i]].begin(), ve[c[i]].end(), i), p});
      pos[a[p]] = 0;
      pos[c[i]] = p;
      a[p] = c[i];
    }else {
      s.erase({i, pos[c[i]]});
      s.insert({*upper_bound(ve[c[i]].begin(), ve[c[i]].end(), i), pos[c[i]]});
    }
  }
  cout << ans;
  return 0;
}

标签:NordicOI,ve,int,sum,MAXN,vec,2023,using
From: https://www.cnblogs.com/yaosicheng124/p/18473776

相关文章

  • P9731 [CEOI2023] Balance 题解
    首先考虑\(S=2\)怎么做,我们把它转化为图论问题。对于每一行的两个点的颜色连一条无向边,那我们相当于要给这些边定向。最后要求\(|in_u-out_u|\le1\)。会发现这个要求很像欧拉回路。但是欧拉回路是要求每个点的入度和出度相等,怎么办呢?我们再建一个超级源点,向每个奇数度数的点......
  • 汽车免拆诊断案例 | 2023款零跑C01纯电车后备厢盖无法电动打开和关闭
    故障现象一辆2023款零跑C01纯电车,累计行驶里程约为2万km,车主进厂反映,后备厢盖无法电动打开和关闭。故障诊断接车后试车,操作后备厢盖外侧、驾驶人侧及遥控钥匙上的后备厢盖开启按钮,可以听到后备厢盖解锁的“咔哒”声,但后备厢盖均无法电动打开。手动打开后备厢盖,点按后备......
  • 2023杭电多校4
    2023杭电多校4C-SimpleSetProblem题目描述:一共T组输入,每组输入有K个集合,从K个集合中选取K个数,也就是每个集合选取一个数,问这些数字中的最大值减去这些数字中的最小值的最小的值。解题思路:利用双指针,对于每一个右端点,存一段至少包含所有集合的点各一个的区间,然后就......
  • TuxeraNTFS2023破解版软件dmg安装包(苹果系统读写win分区软件)
    ......
  • 2023年 10月自考《软件开发工具》03173试题
    目录一.单选题二.填空题三.简答题四.应用题一.单选题1.软件对可维护性、可重用性的要求越来越高,这是因为A.客观世界的复杂性B.软件的多样性C.客观世界的动态性D.软件的规模性2.时序网络用户描述 P58页A.数据内容B.程序执行的逻辑过程C.数据结果D.系统状态及......
  • 「CEOI2023」Balance
    感觉这种题天克我啊。。题目给出了\(S=2^k\)的限制,让我们有一些奇怪的思考,再加上有\(S=2\)的部分分,我们可以考虑从\(S=2\)拓展到任意情况。故我们先研究\(S=2\)的情况。我们对颜色建点,对于每一行的两种颜色之间连一条边。然后我们考虑钦定每一条边的方向以表示这一行的......
  • ICPC WF 2022 2023 Bridging the Gap 过桥
    https://qoj.ac/problem/8683https://loj.ac/p/6937是个十足的DP题。刷完了YeahPotato的DP博客,你觉得有什么方法能套进来呢?前面“基于特殊结构的技巧”没有一个能用。如何分析性质?分析样例:1238996991088345明显先排序。3456888999910猜想......
  • 国家人工智能创新应用先导区数据及城市人工智能先导区准自然实验数据(2006-2023年)
    一、测算方式:参考C刊《当代财经》冯婉昕(2024)老师的做法,本文的核心解释变量为国家人工智能创新应用先导区政策(AI)。企业的金融资产配置是企业生产经营的内生变量,因此,如果选择企业层面的指标来度量企业人工智能应用情况,会面临较大的内生性问题,从而无法识别人工智能应用与金融资产......
  • 【bayes-Transformer多维时序预测】bayes-Transformer多变量时间序列预测,基于bayes-Tr
    %% 划分训练集和测试集P_train=res(1:num_train_s,1:f_)';T_train=res(1:num_train_s,f_+1:end)';P_test=res(num_train_s+1:end,1:f_)';T_test=res(num_train_s+1:end,f_+1:end)';%% 划分训练集和测试集M=size(P_train,2);N=siz......
  • 【题解】[2023 合肥蜀山初中] 旅行(travel)
    题目传送门题目大意有一个\(n\)个点\(m\)条边的有向图组成的城市,每条边可以是骑行边或公共交通边,公共交通边只能走一条,边是从\(u_i\)到\(v_i\)的有向边,需要花费\(time_i\)的时间,求\(1\)到其他点的最短路径。思路分析有一个很巧妙的思路叫分层图,它的思路是因为只能......