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 }
ezoj 1222 [RYOI2018R2]补番计划
posted @ 2018-09-01 21:51  KingSann  阅读(159)  评论(0编辑  收藏  举报