ezoj 1222 [RYOI2018R2]补番计划
给定一个序列,每个位置都有一个颜色,支持两种操作
1. 给定$l,r,k$,问下标在$[l,r]$的位置上有多少个颜色$k$
2. 给定$p,k$,将下标为$p$的位置上的颜色变为$k$
强制在线
对于100%的数据,n,m<=7'00'000。
所有特征值ai均不超过MAX_INT且非负。
时间限制3s,空间限制40M。
考虑一下没有修改怎么做
用vector记录一下每个颜色的出现位置,查询直接在上面二分
带修改的话就用平衡树维护一下就行了
1 #include <bits/stdc++.h> 2 #include <bits/extc++.h> 3 using namespace __gnu_pbds; 4 using namespace std; 5 typedef long long ll; 6 const int N = 7e5 + 10; 7 8 int n, m, sz[N], lc[N], rc[N], root[N], val[N]; 9 10 void up(int x) { sz[x] = sz[lc[x]] + sz[rc[x]] + 1; } 11 12 pair<int, int> split(int x, int k) { 13 pair<int, int> res; 14 if(x) { 15 if(sz[lc[x]] >= k) { 16 res = split(lc[x], k); 17 lc[x] = res.second; 18 res.second = x; 19 } else { 20 res = split(rc[x], k - sz[lc[x]] - 1); 21 rc[x] = res.first; 22 res.first = x; 23 } 24 up(x); 25 } 26 return res; 27 } 28 29 int merge(int x, int y) { 30 if(!x || !y) return x | y; 31 if(rand() % (sz[x] + sz[y]) < sz[x]) { 32 rc[x] = merge(rc[x], y); 33 up(x); 34 return x; 35 } else { 36 lc[y] = merge(x, lc[y]); 37 up(y); 38 return y; 39 } 40 } 41 42 queue<int> rs; 43 int nd(int val) { 44 static int tot = 0; 45 if(rs.size()) { 46 int u = rs.front(); rs.pop(); 47 if(lc[u]) rs.push(lc[u]); 48 if(rc[u]) rs.push(rc[u]); 49 lc[u] = rc[u] = 0, sz[u] = 1, :: val[u] = val; 50 return u; 51 } else { 52 ++ tot; 53 :: val[tot] = val; 54 sz[tot] = 1; 55 return tot; 56 } 57 } 58 59 int le(int x, int v) { 60 if(!x) return 0; 61 if(v >= val[x]) return sz[lc[x]] + 1 + le(rc[x], v); 62 return le(lc[x], v); 63 } 64 65 void ins(int &x, int v) { 66 pair<int, int> res = split(x, le(x, v)); 67 x = merge(res.first, merge(nd(v), res.second)); 68 } 69 70 void dfs(int u) { 71 if(u) dfs(lc[u]), printf("%d ", val[u]), dfs(rc[u]); 72 } 73 74 void del(int &x, int v) { 75 pair<int, int> res = split(x, le(x, v - 1)); 76 pair<int, int> ser = split(res.second, 1); 77 if(ser.first) rs.push(ser.first); 78 x = merge(res.first, ser.second); 79 } 80 81 cc_hash_table<int, int> tr; 82 int tot, a[N]; 83 84 inline int read() { 85 int x = 0, c = 0; 86 while(!isdigit(c)) c = getchar(); 87 while(isdigit(c)) x = x * 10 + c - '0', c = getchar(); 88 return x; 89 } 90 91 int main() { 92 n = read(), m = read(); 93 for(int i = 1, x ; i <= n ; ++ i) { 94 x = a[i] = read(); 95 if(tr.find(x) == tr.end()) tr[x] = ++ tot; 96 ins(root[tr[x]], i); 97 } 98 for(int i = 1, lastans = 0 ; i <= m ; ++ i) { 99 if(read() == 1) { 100 int l = ((ll) read() + lastans) % n + 1; 101 int r = ((ll) read() + lastans) % n + 1; 102 int k = read(); 103 if(l > r) swap(l, r); 104 if(tr.find(k) == tr.end()) lastans = 0; 105 else lastans = le(root[tr[k]], r) - le(root[tr[k]], l - 1); 106 printf("%d\n", lastans); 107 } else { 108 int p = ((ll) read() + lastans) % n + 1; 109 int x = read(); 110 if(tr.find(x) == tr.end()) tr[x] = ++ tot; 111 del(root[tr[a[p]]], p); 112 ins(root[tr[x]], p); 113 a[p] = x; 114 } 115 } 116 }