[]
What a problem! I thought I had to spend more than a week to solve it. Fortunately, it didn't cost me so much time.
[Solution]
I thought of segment tree + balanced tree + splay at first. Use segment tree to refrence the value, use sbt to modify the position, and it must be dynamic where splay is used. It's log^3(n), which would certainly TLE!
Then I tried scopegoat tree + dynamic segment tree. It's log^2(n), although I have never coded scopegoat tree before.
Scopegoat tree is a balanced tree. After each insert operation, check every node on the path, and choose the most unbalanced one. If it's sort of unbalanced, simply rebuild the whole sub-tree. It can be proved that the time complex is still O(n lgn), but I don't know how to prove it. Maybe imagine.
Then a trash recycle system is in need to prevent from MLE. After trying a long, I used the same strategy as that I used in Sequence(NOI2014).
[Code]
So long and ugly and slow!
#include <cstdio>
#include <cctype>
#include <memory.h>
#include <queue>
#include <algorithm>
using namespace std;
int nextInt() {
int d, s = 0;
do
d = getchar();
while (!isdigit(d));
do
s = s * 10 + d - 48, d = getchar();
while (isdigit(d));
return s;
}
const int maxn = 70009;
const int maxl = 57;
const int pssz = 2000000;
struct seg {
int v, c;
seg *ls, *rs;
};
#define von(p) ((p)?(p->v):0)
#define lson(p) ((p)?(p->ls):0)
#define rson(p) ((p)?(p->rs):0)
struct segtree {
seg *sp, *can[pssz];
int tcan, csp;
void expTrash(seg* p) {
if (p-> ls) {
p-> ls-> c --;
if (!p-> ls-> c)
can[tcan ++] = p-> ls;
}
if (p-> rs) {
p-> rs-> c --;
if (!p-> rs-> c)
can[tcan ++] = p-> rs;
}
}
seg* newNode() {
if (tcan) {
seg* r = can[-- tcan];
expTrash(r);
return r;
}
else if (csp)
return -- csp, ++ sp;
else
return csp = pssz, sp = new seg[pssz];
}
void init() {
tcan = 0;
csp = 0;
}
void recycle(seg* p) {
if (!p)
return;
else if (!p-> c) {
can[tcan ++] = p;
}
else if (p-> c < 0)
puts("recycle error");
}
seg* chg(seg* q, int p0, int v0) {
seg *s = newNode(), *p = s;
int l = 0, r = maxn;
while (l < r) {
p-> v = von(q) + v0;
p-> c = 1;
int mid = (l + r) >> 1;
if (p0 <= mid) {
p-> rs = rson(q);
if (p-> rs)
p-> rs-> c ++;
q = lson(q);
p-> ls = newNode();
p = p-> ls;
r = mid;
}
else {
p-> ls = lson(q);
if (p-> ls)
p-> ls-> c ++;
q = rson(q);
p-> rs = newNode();
p = p-> rs;
l = mid + 1;
}
}
p-> v = von(q) + v0;
p-> c = 1;
p-> ls = 0;
p-> rs = 0;
return s;
}
seg* merge(seg* p, seg* q, int l = 0, int r = maxn) {
if (!p && !q)
return 0;
if (!p) {
q-> c ++;
return q;
}
else if (!q) {
p-> c ++;
return p;
}
else {
seg* s = newNode();
s-> v = von(p) + von(q);
s-> c = 1;
if (l < r) {
int mid = (l + r) >> 1;
s-> ls = merge(lson(p), lson(q), l, mid);
s-> rs = merge(rson(p), rson(q), mid + 1, r);
}
return s;
}
}
};
segtree sgt;
const double balanceConst = 0.75;
struct scapegoattree {
int rt, ls[maxn], rs[maxn], sz[maxn], vl[maxn], buf[maxn], cbuf, tn;
seg* sr[maxn];
void update(int p) {
sz[p] = sz[ls[p]] + sz[rs[p]] + 1;
sr[p] = sgt. merge(sr[ls[p]], sr[rs[p]]);
seg* sold = sr[p];
sr[p] = sgt. chg(sr[p], vl[p], 1);
sgt. recycle(sold);
}
void travel(int p) {
if (!p)
return;
travel(ls[p]);
buf[++ cbuf] = p;
if (sr[p]) {
sr[p]-> c = 0;
sgt. recycle(sr[p]);
}
travel(rs[p]);
}
int rebuild(int p) {
cbuf = 0;
travel(p);
return build(1, cbuf);
}
inline double balanceVal(int p) {
return (double)(max(sz[ls[p]], sz[rs[p]])) / (double)sz[p];
}
void init() {
tn = 0;
rt = 0;
sz[0] = 0;
sr[0] = 0;
}
int addBuf(int v0) {
int p = ++ tn;
vl[p] = v0;
sr[p] = 0;
buf[++ cbuf] = p;
return p;
}
int build(int l, int r) {
if (l > r)
return 0;
int mid = (l + r) >> 1;
int p = buf[mid];
ls[p] = build(l, mid - 1);
rs[p] = build(mid + 1, r);
update(p);
return p;
}
void build() {
rt = build(1, cbuf);
}
void change(int p0, int v0) {
int p = rt, rp[maxl], trp = 0, vo;
while (p) {
rp[++ trp] = p;
seg* sold = sr[p];
sr[p] = sgt. chg(sr[p], v0, 1);
sold-> c --;
sgt. recycle(sold);
if (sz[ls[p]] + 1 == p0) {
vo = vl[p];
vl[p] = v0;
break;
}
else if (sz[ls[p]] >= p0)
p = ls[p];
else
p0 -= sz[ls[p]] + 1, p = rs[p];
}
for (int i = 1; i <= trp; i ++) {
seg* sold = sr[rp[i]];
sr[rp[i]] = sgt. chg(sr[rp[i]], vo, -1);
sold-> c --;
sgt. recycle(sold);
}
}
void insert(int p0, int v0) {
int pi = ++ tn;
ls[pi] = 0;
rs[pi] = 0;
sz[pi] = 1;
vl[pi] = v0;
sr[pi] = sgt. chg(0, v0, 1);
int p = rt, rp[maxl], trp = 0;
if (p0 == sz[p] + 1) {
while (p) {
rp[++ trp] = p;
sz[p] ++;
seg* sold = sr[p];
sr[p] = sgt. chg(sr[p], v0, 1);
sold-> c --;
sgt. recycle(sold);
if (rs[p])
p = rs[p];
else
break;
}
rs[p] = pi;
}
else {
while (p) {
rp[++ trp] = p;
sz[p] ++;
seg* sold = sr[p];
sr[p] = sgt. chg(sr[p], v0, 1);
sold-> c --;
sgt. recycle(sold);
if (sz[ls[p]] + 1 == p0)
break;
else if (sz[ls[p]] >= p0)
p = ls[p];
else
p0 -= sz[ls[p]] + 1, p = rs[p];
}
if (!ls[p])
ls[p] = pi;
else {
p = ls[p];
while (p) {
rp[++ trp] = p;
sz[p] ++;
seg* sold = sr[p];
sr[p] = sgt. chg(sr[p], v0, 1);
sold-> c --;
sgt. recycle(sold);
if (!rs[p])
break;
else
p = rs[p];
}
rs[p] = pi;
}
}
int pc = -1;
double mc = 0;
for (int i = trp; i; i --)
if (balanceVal(rp[i]) > mc)
mc = balanceVal(rp[i]), pc = i;
if (mc > balanceConst) {
int rn = rebuild(rp[pc]);
if (pc > 1) {
if (rp[pc] == ls[rp[pc - 1]])
ls[rp[pc - 1]] = rn;
else
rs[rp[pc - 1]] = rn;
}
else
rt = rn;
}
}
void getChain(seg** a, int& t, int k) {
int p = rt;
t = 0;
while (p && k)
if (sz[ls[p]] == k) {
a[t ++] = sr[ls[p]];
if (sr[ls[p]])
sr[ls[p]]-> c ++;
break;
}
else if (sz[ls[p]] < k) {
a[t] = sgt. chg(sr[ls[p]], vl[p], 1);
a[t ++]-> c = 0;
k -= sz[ls[p]] + 1;
p = rs[p];
}
else
p = ls[p];
}
int query(int l0, int r0, int k) {
seg *cl[maxl], *cr[maxl], *rold[maxl * 2];
int tl, tr;
getChain(cl, tl, l0 - 1);
getChain(cr, tr, r0);
for (int i = 0; i < tl; i ++)
rold[i] = cl[i];
for (int i = 0; i < tr; i ++)
rold[tl + i] = cr[i];
int l = 0, r = maxn;
while (l < r) {
int s = 0;
for (int i = 0; i < tl; i ++)
s -= von(lson(cl[i]));
for (int i = 0; i < tr; i ++)
s += von(lson(cr[i]));
if (s >= k) {
r = (l + r) >> 1;
for (int i = 0; i < tl; i ++)
cl[i] = lson(cl[i]);
for (int i = 0; i < tr; i ++)
cr[i] = lson(cr[i]);
}
else {
k -= s;
l = ((l + r) >> 1) + 1;
for (int i = 0; i < tl; i ++)
cl[i] = rson(cl[i]);
for (int i = 0; i < tr; i ++)
cr[i] = rson(cr[i]);
}
}
for (int i = 0; i < tl + tr; i ++)
if (rold[i])
sgt. recycle(rold[i]);
return l;
}
void debOut(int p = -1) {
if (p == -1)
p = rt;
if (!p)
return;
debOut(ls[p]);
printf("%4d", vl[p]);
debOut(rs[p]);
if (p == rt)
printf(" length = %d\n", sz[p]);
}
};
scapegoattree sct;
int n, m, lans;
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
sgt. init();
sct. init();
n = nextInt();
for (int i = 1; i <= n; i ++)
sct. addBuf(nextInt());
sct. build();
m = nextInt();
lans = 0;
while (m --) {
char opt;
int x, y, z;
scanf("\n%c", &opt);
if (opt == 'Q') {
x = nextInt() ^ lans;
y = nextInt() ^ lans;
z = nextInt() ^ lans;
printf("%d\n", (lans = sct. query(x, y, z)));
}
else if (opt == 'M') {
x = nextInt() ^ lans;
y = nextInt() ^ lans;
sct. change(x, y);
}
else if (opt == 'I') {
x = nextInt() ^ lans;
y = nextInt() ^ lans;
sct. insert(x, y);
}
}
}