[BZOJ1901]Zju2112 Dynamic Rankings

[BZOJ1901]Zju2112 Dynamic Rankings

试题描述

给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。

输入

输出

对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

输入示例

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

输出示例

3
6

数据规模及约定

见“试题描述

题解

打了一波线段树套 treap,相比于主席树套树状数组来说慢多了。。。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
	return x * f;
}

#define maxn 10005
#define maxnode 1280010
struct Node {
	int v, r, siz;
	Node() {}
	Node(int _, int __): v(_), r(__) {}
} ns[maxnode];
int ToT, rt[maxn<<2], fa[maxnode], ch[2][maxnode];
void maintain(int o) {
	ns[o].siz = 1;
	for(int i = 0; i < 2; i++) if(ch[i][o])
		ns[o].siz += ns[ch[i][o]].siz;
	return ;
}
void rotate(int u) {
	int y = fa[u], z = fa[y], l = 0, r = 1;
	if(z) ch[ch[1][z]==y][z] = u;
	if(ch[1][y] == u) swap(l, r);
	fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
	ch[l][y] = ch[r][u]; ch[r][u] = y;
	maintain(y); maintain(u);
	return ;
}
void insert(int& o, int v) {
	if(!o) {
		ns[o = ++ToT] = Node(v, rand());
		return maintain(o);
	}
	bool d = v > ns[o].v;
	insert(ch[d][o], v); fa[ch[d][o]] = o;
	if(ns[ch[d][o]].r > ns[o].r) {
		int t = ch[d][o];
		rotate(t); o = t;
	}
	return maintain(o);
}
void del(int& o, int v) {
	if(!o) return ;
	if(ns[o].v == v) {
		if(!ch[0][o] && !ch[1][o]) o = 0;
		else if(!ch[0][o]) {
			int t = ch[1][o]; fa[t] = fa[o]; o = t;
		}
		else if(!ch[1][o]) {
			int t = ch[0][o]; fa[t] = fa[o]; o = t;
		}
		else {
			bool d = ns[ch[1][o]].r > ns[ch[0][o]].r;
			int t = ch[d][o]; rotate(t); o = t;
			del(ch[d^1][o], v);
		}
	}
	else {
		bool d = v > ns[o].v;
		del(ch[d][o], v);
	}
	return maintain(o);
}
int Find(int o, int v) {
	if(!o) return 0;
	int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
	if(v >= ns[o].v) return ls + 1 + Find(ch[1][o], v);
	return Find(ch[0][o], v);
}

int n, val[maxn];
void build(int L, int R, int o, int p) {
	insert(rt[o], val[p]);
	if(L == R) return ;
	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
	if(p <= M) build(L, M, lc, p);
	else build(M+1, R, rc, p);
	return ;
}
void update(int L, int R, int o, int p, int v) {
	del(rt[o], val[p]); insert(rt[o], v);
	if(L == R) return ;
	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
	if(p <= M) update(L, M, lc, p, v);
	else update(M+1, R, rc, p, v);
	return ;
}
int ql, qr;
int query(int L, int R, int o, int v) {
	if(ql <= L && R <= qr) return Find(rt[o], v);
	int M = L + R >> 1, lc = o << 1, rc = lc | 1, ans = 0;
	if(ql <= M) ans += query(L, M, lc, v);
	if(qr > M) ans += query(M+1, R, rc, v);
	return ans;
}

int main() {
	n = read(); int q = read();
	for(int i = 1; i <= n; i++) val[i] = read(), build(1, n, 1, i);
	
	while(q--) {
		char tp[2]; scanf("%s", tp);
		if(tp[0] == 'Q') {
			ql = read(); qr = read(); int k = read();
			int l = 0, r = (int)1e9; bool has = 0;
			while(l < r) {
				int mid = l + r >> 1;
				if(query(1, n, 1, mid) < k) {
					l = mid + 1;
					if(query(1, n, 1, l) >= k){ has = 1; printf("%d\n", l); break; }
				}
				else r = mid;
			}
			if(!has) printf("%d\n", l);
		}
		else {
			int p = read(), v = read();
			update(1, n, 1, p, v);
			val[p] = v;
		}
	}
	
	return 0;
}

 

posted @ 2016-12-10 15:42  xjr01  阅读(...)  评论(...编辑  收藏