bzoj3196
http://www.lydsy.com/JudgeOnline/problem.php?id=3196
树套树!
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 3000010, inf = 1000000000; int n, m, cnt; int a[N]; namespace splaytree { int child[N][2], size[N], fa[N], key[N], root[N], num[N]; void update(int x) { size[x] = num[x] + size[child[x][0]] + size[child[x][1]]; } void zig(int x) { int y = fa[x]; fa[x] = fa[y]; child[fa[x]][child[fa[x]][1] == y] = x; child[y][0] = child[x][1]; fa[child[x][1]] = y; fa[y] = x; child[x][1] = y; update(y); update(x); } void zag(int x) { int y = fa[x]; fa[x] = fa[y]; child[fa[x]][child[fa[x]][1] == y] = x; child[y][1] = child[x][0]; fa[child[x][0]] = y; fa[y] = x; child[x][0] = y; update(y); update(x); } void splay(int x, int t, int pos) { while(fa[x] != t) { int y = fa[x], z = fa[y]; if(z == t) { child[y][0] == x ? zig(x) : zag(x); break; } else if(y == child[z][0] && x == child[y][0]) { zig(y); zig(x); } else if(y == child[z][1] && x == child[y][1]) { zag(y); zag(x); } else if(y == child[z][0] && x == child[y][1]) { zag(x); zig(x); } else if(y == child[z][1] && x == child[y][0]) { zig(x); zag(x); } } if(!t) root[pos] = x; update(root[pos]); } int getrnk(int x, int k) { int ret = 0; while(x) { if(k == key[x]) { ret += (child[x][0] ? size[child[x][0]] : 0); break; } if(k > key[x]) { ret += num[x] + size[child[x][0]]; x = child[x][1]; } else x = child[x][0]; } return ret; } void up(int x) { while(x) { update(x); x = fa[x]; } } int find(int x, int k) { for(int now = x; now; now = child[now][k > key[now]]) if(key[now] == k) return now; } void del(int x, int k) { splay(k, 0, x); if(num[k] > 1) { --num[k]; up(k); return; } if(child[k][0] * child[k][1] == 0) { root[x] = child[k][0] + child[k][1]; fa[root[x]] = 0; fa[k] = child[k][0] = child[k][1] = num[k] = size[k] = key[k] = 0; update(root[x]); return; } int now = child[k][1]; while(child[now][0]) now = child[now][0]; fa[child[k][0]] = now; child[now][0] = child[k][0]; root[x] = child[k][1]; fa[root[x]] = 0; up(child[k][0]); fa[k] = child[k][0] = child[k][1] = size[k] = num[k] = 0; splay(now, 0, x); } void insert(int x, int k) { if(!root[x]) { root[x] = ++cnt; num[cnt] = size[cnt] = 1; key[cnt] = k; return; } int now = root[x]; while(1) { if(key[now] == k) { ++num[now]; up(now); return; } if(!child[now][k > key[now]]) { child[now][k > key[now]] = ++cnt; num[cnt] = size[cnt] = 1; fa[cnt] = now; key[cnt] = k; up(cnt); return; } now = child[now][k > key[now]]; } } int Pre(int x, int k) { int now = root[x], ret = 0; while(now) { if(key[now] < k) ret = max(ret, key[now]); if(key[now] < k) now = child[now][1]; else now = child[now][0]; } return ret; } int Nxt(int x, int k) { int now = root[x], ret = inf; while(now) { if(key[now] > k) ret = min(ret, key[now]); if(key[now] > k) now = child[now][0]; else now = child[now][1]; } return ret; } } using namespace splaytree; namespace segmenttree { void build(int l, int r, int x) { if(l == r) { root[x] = ++cnt; size[cnt] = num[cnt] = 1; key[cnt] = a[l]; return; } int mid = (l + r) >> 1; build(l, mid, x << 1); build(mid + 1, r, x << 1 | 1); for(int i = l; i <= r; ++i) insert(x, a[i]); } int query1(int l, int r, int x, int a, int b, int k) { //一个数在区间内的排名 if(l > b || r < a) return 0; if(l >= a && r <= b) return getrnk(root[x], k); int mid = (l + r) >> 1; return (query1(l, mid, x << 1, a, b, k) + query1(mid + 1, r, x << 1 | 1, a, b, k)); } int querynum(int l, int r, int k) { int L = 0, R = 100000010, mid, ans = -1; while(R - L > 1) { mid = (L + R) >> 1; int t = query1(1, n, 1, l, r, mid); if(t < k) L = mid; else R = mid; } return L; } void modify(int l, int r, int x, int pos, int k) { if(l == r) { root[x] = ++cnt; key[cnt] = k; num[cnt] = size[cnt] = 1; return; } int mid = (l + r) >> 1; if(pos <= mid) modify(l, mid, x << 1, pos, k); else modify(mid + 1, r, x << 1 | 1, pos, k); int t = find(root[x], a[pos]); del(x, t); insert(x, k); } int query3(int l, int r, int x, int a, int b, int k) { //找前继 if(l > b || r < a) return -inf; if(l >= a && r <= b) return Pre(x, k); int mid = (l + r) >> 1; return max(query3(l, mid, x << 1, a, b, k), query3(mid + 1, r, x << 1 | 1, a, b, k)); } int query4(int l, int r, int x, int a, int b, int k) { // printf("l=%d r=%d\n", l, r); if(l > b || r < a) return inf; if(l >= a && r <= b) return Nxt(x, k); int mid = (l + r) >> 1; return min(query4(l, mid, x << 1, a, b, k), query4(mid + 1, r, x << 1 | 1, a, b, k)); } } using namespace segmenttree; int main() { // freopen("psh.in", "r", stdin); // freopen("psh.out", "w", stdout); scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); build(1, n, 1); while(m--) { int opt, l, r, k, pos, t = 0; scanf("%d", &opt); if(opt == 1) { scanf("%d%d%d", &l, &r, &k); printf("%d\n", query1(1, n, 1, l, r, k) + 1); } if(opt == 2) { scanf("%d%d%d", &l, &r, &k); printf("%d\n", querynum(l, r, k)); } if(opt == 3) { scanf("%d%d", &pos, &k); modify(1, n, 1, pos, k); a[pos] = k; } if(opt == 4) { scanf("%d%d%d", &l, &r, &k); printf("%d\n", query3(1, n, 1, l, r, k)); } if(opt == 5) { scanf("%d%d%d", &l, &r, &k); printf("%d\n", query4(1, n, 1, l, r, k)); } } // fclose(stdin); fclose(stdout); return 0; }