带修莫队+离散化 TLE,悬关,求大佬垂青

P2464 [SDOI2008] 郁闷的小 J

```cpp #include<bits/stdc++.h> using namespace std; const int N = 1e6; int n, m, r, q, tot; int val[N], ans[N], len, bel[N], cnt[N]; //书的编码 | 答案 | 块长 | 对应块 | 编码本数 vector<int> all; //离散化数组 struct Change{ //存储修改操作 int x, v; //位置,值 } C[N]; struct Query{ //存储查询操作 int l, r, t, k, id; //左、右端点,时刻,值,顺序 } Q[N]; bool cmp(Query x, Query y) { //带修莫队,对左右端点都分了块 return (bel[x.l] == bel[y.l]) ? ((bel[x.r] == bel[y.r]) ? x.t < y.t : x.r < y.r) : x.l < y.l; } int main() { scanf("%d%d", &n, &m); len = sqrt(n); for (int i = 1; i <= n; i ++) { scanf("%d", &val[i]); bel[i] = (i-1) / len + 1; all.push_back(val[i]); } for (int i = 1; i <= m; i ++) { char op[2]; int a, b, k; scanf("%s%d%d", &op, &a, &b); if (op[0] == 'C') C[++ r] = {a, b}, all.push_back(b); else { scanf("%d", &k); Q[++ q] = {a, b, r, k, q}; all.push_back(k); } } //输入 sort(all.begin(), all.end()); tot = unique(all.begin(), all.end()) - all.begin(); for (int i = 1; i <= n; i ++) val[i] = lower_bound(all.begin(), all.end(), val[i]) - all.begin(); for (int i = 1; i <= r; i ++) C[i].v = lower_bound(all.begin(), all.end(), C[i].v) - all.begin(); for (int i = 1; i <= q; i ++) Q[i].k = lower_bound(all.begin(), all.end(), Q[i].k) - all.begin(); sort(Q+1, Q+q+1, cmp); //离散化 int l = 1, r = 0, t = 0; //左指针、右指针、时间点 for (int i = 1; i <= q; i ++) { int L = Q[i].l, R = Q[i].r, T = Q[i].t; while (l > L) cnt[val[-- l]] ++; while (r < R) cnt[val[++ r]] ++; while (l < L) cnt[val[l ++]] --; while (r > R) cnt[val[r --]] --; while (t < T) { ++ t; if (C[t].x <= R && C[t].x >= L) cnt[val[C[t].x]] --, cnt[C[t].v] ++; swap(val[C[t].x], C[t].v); } while (t > T) { if (C[t].x <= R && C[t].x >= L) cnt[val[C[t].x]] --, cnt[C[t].v] ++; swap(val[C[t].x], C[t].v); t --; } ans[Q[i].id] = cnt[Q[i].k]; } //莫队 for (int i = 1; i <= q; i ++) printf("%d\n", ans[i]); //输出 } ```
by Arson1st @ 2023-10-18 10:58:22


更新:将块长调为 $n^{\frac{2}{3}}$ 后可做到无氧90pts,吸氧AC……不知道还有什么地方可以再优化了
by Arson1st @ 2023-10-18 11:20:59


|