扩大
缩小

BZOJ3217 ALOEXT

3217: ALOEXT

Time Limit: 25 Sec  Memory Limit: 512 MB

Description

taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手。

突然有一天,taorunz来到了一个密室,里面放着一排可移动存储器,存储器里有非常珍贵的OI资料……不过比较特殊的是,每个存储器上都写着一个非负整数。taorunz很高兴,要把所有的存储器都拿走(taorunz的智商高达500,他一旦弄走了这里的所有存储器,在不久到来的AHOI和NOI中……你懂的)。不过这时有一个声音传来:“你只能拿走这里的一个存储器,而且还不能直接拿,你需要指定一段区间[l, r],满足l<r,然后在第l个和第r个存储器之间选一个拿走,你能获得的知识增加量等于区间[l, r]中所有存储器上写的整数的次大值与你拿走的这个存储器上写的整数作按位异或运算的结果。”

问题是,这里的可移动存储器数量太多,而且,它们还在不断地发生变化,有时候天上会掉下来一个新的存储器,并插入到这一排存储器中,有时候某个存储器会不明原因消失,有时候某个存储器上写的整数变化了。taorunz虽然智商很高,但也无法应对如此快的变化,他指定了许多段区间,让你帮他找出如果在这个区间中拿走存储器,他能获得的最多的知识是多少。

Input

第一行两个整数N、M,表示一开始的存储器数和后面发生的事件数。

第二行N个非负整数,表示一开始从左到右每个存储器上写的数字。注意,存储器从0开始编号,也就是最左边的存储器是第0个。

接下来M行,每行描述一个事件,有4种可能的事件。

(1)I x y:表示天上掉下来一个写着数字y的存储器,并插入到原来的第x个存储器之前,如果x等于原来存储器的个数,则插入到末尾;

(2)[D] x:表示第x个存储器消失;

(3)C x y:表示第x个存储器上写的数字变为y;

(4)F l r:表示taorunz指定区间[l, r],让你告诉他最多能获得多少知识。

注意,本题强制在线,也就是事件中出现的所有数字都进行了加密,数字s表示的真实值是

对于I、[D]、C事件中的x及F事件中的l、r:(s+last_ans) mod n0;

对于I、C事件中的y:(s+last_ans) mod 1048576。

其中n0为目前存储器个数,last_ans为上一个F事件的结果,如果前面尚未发生F事件,则last_ans=0。

Output

对于每个F事件,输出结果。

Sample Input

5 10
2 6 3 8 7
F 1 4
I 2 1048565
I 0 1048566
D 3
F 3 0
I 3 1048569
D 5
C 1 1048570
F 1 2
F 2 1

Sample Output

15
7
4
7

HINT

1<=N, M<=100000。所有F事件满足l<r。
本题共有5组数据,除1组为随机数据外,其它数据均为人工构造。

Source

By mato_no1


又是一道卡了3天的神犇树套树。

首先,样例有问题,[D]在测试数据里是D。

好吧,替罪羊套trie,听着就sb,写起来也sb的题,替罪羊爱咋写咋写

删除是本题唯一的难点,不能直接删,删了的话替罪羊就会开始疯狂重构,直接GG,打个标记,咱当这点不存在。

所以记录一个sz,一个max_sz,sz就是还被删除的点的个数,max_sz是总和,序列找点用sz,平时的sz + 1等要改成sz + (!t[rt].del),替罪羊判断是否重构用max_sz,重构也不要删掉打了标记的点。网上有大佬用类似线段树的方式建替罪羊,把序列全部建在叶子节点,这样就避免的删除带来的困扰,但他的代码在我对拍的时候GG了,大家观摩思想就好,别抄代码。。。

然后就没有然后了,题目有点卡,alpha推荐0.75。


ACcode:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 template <class _T> inline void read(_T &_x) {
  4     int _t; bool flag = false;
  5     while ((_t = getchar()) != '-' && (_t < '0' || _t > '9')) ;
  6     if (_t == '-') _t = getchar(), flag = true; _x = _t - '0';
  7     while ((_t = getchar()) >= '0' && _t <= '9') _x = _x * 10 + _t - '0';
  8     if (flag) _x = -_x;
  9 }
 10 typedef long long LL;
 11 const int DEP = 20;
 12 const int maxv = 200010;
 13 const int MOD = 1048576;
 14 namespace T {
 15     const int maxt = maxv * DEP * 8;
 16     struct Tnode {
 17         int v, ch[2];
 18     }t[maxt];
 19     int st[maxt], top, tot;
 20     inline int newnode() {
 21         if (!top) st[top++] = ++tot;
 22         int cur = st[--top];
 23         t[cur].v = t[cur].ch[0] = t[cur].ch[1] = 0;
 24         return cur;
 25     }
 26     void reclaim(int rt) {
 27         if (!rt) return ;
 28         reclaim(t[rt].ch[0]), reclaim(t[rt].ch[1]);
 29         st[top++] = rt;
 30     }
 31     void insert(int &rt, int val, int dep) {
 32         if (!rt) rt = newnode(); ++t[rt].v;
 33         if (dep < 0) return ;
 34         insert(t[rt].ch[(val>>dep)&1], val, dep - 1);
 35     }
 36     void remove(int &rt, int val, int dep) {
 37         --t[rt].v;
 38         if (!t[rt].v) {
 39             reclaim(rt), rt = 0;
 40             return ;
 41         }
 42         if (dep < 0) return ;
 43         remove(t[rt].ch[(val>>dep)&1], val, dep - 1);
 44     }
 45     int merge(int a, int b) {
 46         if (!a && !b) return 0;
 47         int rt = newnode();
 48         t[rt].v = t[a].v + t[b].v;
 49         t[rt].ch[0] = merge(t[a].ch[0], t[b].ch[0]);
 50         t[rt].ch[1] = merge(t[a].ch[1], t[b].ch[1]);
 51         return rt;
 52     }
 53 }
 54 namespace S { //scapegoat
 55     const double alpha = 0.75;
 56     struct Snode {
 57         int v, l, r;
 58         int sz, max_sz, root;
 59         bool del;
 60     }t[maxv];
 61     int st[maxv], top, tot;
 62     int Root;
 63     void print(int rt) {
 64         if (!rt) return ;
 65         //putchar('[');
 66         print(t[rt].l);
 67         if (!t[rt].del) printf("%d ", t[rt].v);
 68         print(t[rt].r);
 69         //putchar(']');
 70     }
 71     inline void Print() {
 72         cout << "Seq: ";
 73         print(Root);
 74         cout << endl;
 75     }
 76     inline bool isbad(int rt) {
 77         return t[rt].max_sz * alpha < max(t[t[rt].l].max_sz, t[t[rt].r].max_sz);
 78     }
 79     inline int newnode(int val) {
 80         if (!top) st[top++] = ++tot;
 81         int cur = st[--top];
 82         t[cur].v = val;
 83         t[cur].root = t[cur].l = t[cur].r = t[cur].del = 0;
 84         t[cur].sz = t[cur].max_sz = 0;
 85         return cur;
 86     }
 87     void reclaim(int rt) {
 88         if (!rt) return ;
 89         reclaim(t[rt].l), reclaim(t[rt].r);
 90         T::reclaim(t[rt].root);
 91         st[top++] = rt;
 92     }
 93     int v0[maxv], cnt;
 94     void dfs_node(int rt) {
 95         if (!rt) return ;
 96         dfs_node(t[rt].l);
 97         v0[++cnt] = t[rt].del ? -1 : t[rt].v;
 98         dfs_node(t[rt].r);
 99     }
100     void build(int &rt, int l, int r) {
101         int mid = (l + r) >> 1;
102         rt = newnode(v0[mid]);
103         if (t[rt].v == -1) t[rt].del = true;
104         if (l < mid) build(t[rt].l, l, mid - 1);
105         if (mid < r) build(t[rt].r, mid + 1, r);
106         t[rt].sz = t[t[rt].l].sz + t[t[rt].r].sz + (!t[rt].del);
107         t[rt].max_sz = t[t[rt].l].max_sz + t[t[rt].r].max_sz + 1;    
108         t[rt].root = T::merge(t[t[rt].l].root, t[t[rt].r].root);
109         if (!t[rt].del) T::insert(t[rt].root, t[rt].v, DEP - 1);
110     }
111     void rebuild(int &rt) {
112         cnt = 0, dfs_node(rt);
113         reclaim(rt);
114         build(rt, 1, cnt);
115     }
116     int badroot;
117     void insert(int &rt, int pos, int val) {
118         if (!rt) {
119             rt = newnode(val);
120             ++t[rt].sz, ++t[rt].max_sz;
121             T::insert(t[rt].root, val, DEP - 1);
122             return ;
123         }
124         ++t[rt].sz, ++t[rt].max_sz;
125         T::insert(t[rt].root, val, DEP - 1);
126         if (pos <= t[t[rt].l].sz + (!t[rt].del)) insert(t[rt].l, pos, val);
127         else insert(t[rt].r, pos - t[t[rt].l].sz - (!t[rt].del), val);
128         if (isbad(rt)) badroot = rt;
129     }
130     int change(int rt, int pos, int val) {
131         int ret = 0;
132         if (!t[rt].del && pos == t[t[rt].l].sz + 1) {
133             ret = t[rt].v, t[rt].v = val;
134             T::insert(t[rt].root, val, DEP - 1),
135             T::remove(t[rt].root, ret, DEP - 1);
136             return ret;
137         }
138         if (pos <= t[t[rt].l].sz) ret = change(t[rt].l, pos, val);
139         else ret = change(t[rt].r, pos - t[t[rt].l].sz - (!t[rt].del), val);
140         T::insert(t[rt].root, val, DEP - 1),
141         T::remove(t[rt].root, ret, DEP - 1);
142         return ret;
143     }
144     int remove(int rt, int pos) {
145         --t[rt].sz;
146         if (!t[rt].del && pos == t[t[rt].l].sz + 1) {
147             t[rt].del = true;
148             T::remove(t[rt].root, t[rt].v, DEP - 1);
149             return t[rt].v;
150         }
151         int ret = 0;
152         if (pos <= t[t[rt].l].sz) ret = remove(t[rt].l, pos);
153         else ret = remove(t[rt].r, pos - t[t[rt].l].sz - (!t[rt].del));
154         T::remove(t[rt].root, ret, DEP - 1);
155         return ret;
156     }
157     inline void Init(int n) {
158         for (int i = 1; i <= n; ++i) read(v0[i]);
159         build(Root, 1, n);
160     }
161     inline void Insert(int pos, int val) {
162         //printf("Insert %d before position %d\n", val, pos);
163         badroot = 0;
164         insert(Root, pos + 1, val);
165         if (badroot) rebuild(badroot);
166     }
167     inline void Change(int pos, int val) {
168         //printf("Change position %d to %d\n", pos, val);
169         change(Root, pos + 1, val);
170     }
171     inline void Delete(int pos) {
172         //printf("Delete position %d\n", pos);
173         remove(Root, pos + 1);
174     }
175     struct Qnode {
176         int v, rt;
177         Qnode(int a = 0, int b = 0):v(a), rt(b) {}
178     }p[maxv], ori[maxv];
179     int pcnt;
180     void dfs_part(int rt, int pos) {
181         if (!pos) return ;
182         if (pos == t[t[rt].l].sz) {
183             p[++pcnt] = Qnode(1, t[t[rt].l].root);
184         } else if (pos < t[t[rt].l].sz) {
185             dfs_part(t[rt].l, pos);
186         } else {
187             p[++pcnt] = Qnode(1, t[rt].root);
188             p[++pcnt] = Qnode(-1, t[t[rt].r].root);
189             dfs_part(t[rt].r, pos - t[t[rt].l].sz - (!t[rt].del));
190         }
191     }
192     inline int Query(int l, int r) {
193         ++l, ++r;
194         //printf("Query in range [%d, %d]\n", l, r);
195         pcnt = 0;
196         dfs_part(Root, l - 1);
197         for (int i = 1; i <= pcnt; ++i) p[i].v = -p[i].v;
198         dfs_part(Root, r);
199         memcpy(ori + 1, p + 1, pcnt * sizeof(Qnode));
200         int ret = 0, k = 2;
201         LL totl, totr;
202         int L = 0, R = (1<<DEP) - 1;
203         for (int dep = DEP - 1; dep >= 0; --dep) {
204             totl = totr = 0;
205             for (int i = 1; i <= pcnt; ++i) {
206                 //totl += p[i].v * T::t[T::t[p[i].rt].ch[0]].v;
207                 totr += p[i].v * T::t[T::t[p[i].rt].ch[1]].v;
208             }
209             //printf("%d - %d & %d - %d: %I64d %I64d\n", L, L + (1<<dep) - 1, L + (1 << dep), R, totl, totr);
210             if (totr < k) {
211                 k -= (int)totr;
212                 R -= 1 << dep;
213                 for (int i = 1; i <= pcnt; ++i)
214                     p[i].rt = T::t[p[i].rt].ch[0];
215             } else {
216                 ret += 1 << dep;
217                 L += 1 << dep;
218                 for (int i = 1; i <= pcnt; ++i)
219                     p[i].rt = T::t[p[i].rt].ch[1];
220             }
221         }
222         //cout << ret << endl;
223         memcpy(p + 1, ori + 1, pcnt * sizeof(Qnode));
224         int ans = 0;
225         for (int dep = DEP - 1; dep >= 0; --dep) {
226             totl = 0, totr = 0;
227             for (int i = 1; i <= pcnt; ++i) {
228                 totl += p[i].v * T::t[T::t[p[i].rt].ch[0]].v;
229                 totr += p[i].v * T::t[T::t[p[i].rt].ch[1]].v;
230             }
231             if (!totl || (totr && ((ret>>dep)&1) == 0)) {
232                 ans += 1 << dep;
233                 for (int i = 1; i <= pcnt; ++i)
234                     p[i].rt = T::t[p[i].rt].ch[1];
235             } else {
236                 for (int i = 1; i <= pcnt; ++i)
237                     p[i].rt = T::t[p[i].rt].ch[0];
238             }    
239         }
240         //cout << ans << endl;
241         return ans ^ ret;
242     }
243 }
244 int main() {
245     //freopen("3217.in", "r", stdin);
246     //freopen("3217.out", "w", stdout);
247     int n, m;
248     read(n), read(m);
249     S::Init(n);
250     char op[20];
251     int lastans = 0, n0 = n;
252     for (int i = 1, a, b; i <= m; ++i) {
253         //S::Print();
254         scanf("%s", op);
255         switch (op[0]) {
256             case 'I':
257                 read(a), read(b);
258                 a = (a + lastans) % n0;
259                 b = (b + lastans) % MOD;
260                 S::Insert(a, b);
261                 ++n0;
262                 break;
263             case 'D':
264                 read(a);
265                 a = (a + lastans) % n0;
266                 S::Delete(a);
267                 --n0;
268                 break;
269             case 'C':
270                 read(a), read(b);
271                 a = (a + lastans) % n0;
272                 b = (b + lastans) % MOD;
273                 S::Change(a, b);
274                 break;
275             case 'F':
276                 read(a), read(b);
277                 a = (a + lastans) % n0;
278                 b = (b + lastans) % n0;
279                 printf("%d\n", lastans = S::Query(a, b));
280                 break;
281         }
282     }
283     return 0;
284 }
View Code

良心数据生成器:

#include<bits/stdc++.h>
using namespace std;
int main () {
    freopen("test.in", "w", stdout);
    srand(time(NULL));
    int n = 5, m = 5;
    cout << n << ' ' << m << endl;
    for (int i = 1; i <= n; ++i) {
        cout << rand() % 100 << ' ';
    }
    cout << endl;
    int n0 = n;
    for (int i = 1, a, b; i <= m; ++i) {
        int op = rand() % 4;
        while (n0 <= 2 && op == 1) op = rand() % 4;
        switch (op) {
            case 0:
                a = rand() % n0;
                b = rand() % 100;
                printf("I %d %d\n", a, b);
                ++n0;
                break;
            case 1:
                a = rand() % n0;
                printf("D %d\n", a);
                --n0;
                break;
            case 2:
                a = rand() % n0;
                b = rand() % 100;
                printf("C %d %d\n", a, b);
                break;
            case 3:
                a = rand() % (n0 - 1);
                b = a + rand() % (n0 - a - 1) + 1;
                printf("F %d %d\n", a, b);
                break;
        }
    }
    return 0;
}
View Code
posted @ 2017-05-05 10:33  HPLV  阅读(204)  评论(0编辑  收藏  举报