记录编号 249035 评测结果 AAAAAAAAAA
题目名称 [TYVJ1730]二逼平衡树 最终得分 100
用户昵称 GravatarFmuckss 是否通过 通过
代码语言 C++ 运行时间 2.375 s
提交时间 2016-04-11 20:47:33 内存使用 35.48 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<time.h>
#include<stdlib.h>
using namespace std;
const int maxn = 5e4+10;
const int inf = 1e8+1;

int n, q;
int a[maxn];

struct node {
	int ls, rs, fa;
	int v, fix, size;
	inline node() {}
	inline node(int fa_, int v_, int fix_) { ls = rs = v = 0, fa = fa_, v = v_, fix = fix_; }
	inline void init() { ls = rs = fa = 0; }
}ns[maxn<<5];
int tot;


class treap {
private:
	int root_;
public:
	inline treap() { root_ = 0; }
	
	inline int root() { return root_; }
	
	inline int size() { return ns[root_].size; }
	
	inline void zig(int tar) {
		int tmp = ns[tar].fa;
		if(ns[ns[tmp].fa].ls == tmp) ns[ns[tmp].fa].ls = tar;
		else ns[ns[tmp].fa].rs = tar;
		ns[tar].fa = ns[tmp].fa;
		
		ns[tmp].ls = ns[tar].rs;
		if(ns[tar].rs) ns[ns[tar].rs].fa = tmp;
		
		ns[tar].rs = tmp; ns[tmp].fa = tar;
		
		ns[tmp].size = ns[ns[tmp].ls].size + ns[ns[tmp].rs].size + 1;
	}
	
	inline void zag(int tar) {
		int tmp = ns[tar].fa;
		if(ns[ns[tmp].fa].ls == tmp) ns[ns[tmp].fa].ls = tar;
		else ns[ns[tmp].fa].rs = tar;
		ns[tar].fa = ns[tmp].fa;
		
		ns[tmp].rs = ns[tar].ls;
		if(ns[tar].ls) ns[ns[tar].ls].fa = tmp;
		
		ns[tar].ls = tmp; ns[tmp].fa = tar;
		
		ns[tmp].size = ns[ns[tmp].ls].size + ns[ns[tmp].rs].size + 1;
	}
	
	inline void rebalance(int now) {
		int fa = ns[now].fa;
		while(fa && ns[now].fix < ns[fa].fix) {
			now == ns[fa].ls ? zig(now) : zag(now);
			fa = ns[now].fa;
		}
		if(fa == 0) root_ = now;
		ns[now].size = ns[ns[now].ls].size + ns[ns[now].rs].size + 1;
	}
	
	int dfs(int fr, int now) {
		int now_root = ++tot;
		ns[now_root] = ns[now];
		ns[now_root].fa = fr;
		if(ns[now].ls) {
			ns[now_root].ls = dfs(now_root, ns[now].ls);
		}
		if(ns[now].rs) {
			ns[now_root].rs = dfs(now_root, ns[now].rs);
		}
		return now_root;
	}
	
	inline void copy(int be, int size) {
		root_ = tot+1;
		dfs(0, be);
	}
	
	inline void set_root(int tar, int num) {
		root_ = num;
		ns[root_] = node(0, tar, rand());
		ns[root_].size = 1;
	}
	
	inline void insert(int tar, int num) {
//		printf("%d\n", num);
		if(!root_) {
			set_root(tar, num);
			return;
		}
		int now = root_;
		while(true) {
			ns[now].size++;
			if(tar < ns[now].v) {
				if(ns[now].ls) now = ns[now].ls;
				else {
					ns[now].ls = num;
					ns[num] = node(now, tar, rand());
					rebalance(num);
					return;
				}
			} else {
				if(ns[now].rs) now = ns[now].rs;
				else {
					ns[now].rs = num;
					ns[num] = node(now, tar, rand());
					rebalance(num);
					return;
				}
			}
		}
	}
	
	inline int find_del(int now) {
		while(ns[now].ls) {
			ns[now].size--;
			now = ns[now].ls;
		}
		int fa = ns[now].fa;
		if(ns[fa].ls == now) ns[fa].ls = ns[now].rs;
		else ns[fa].rs = ns[now].rs;
		if(ns[now].rs) ns[ns[now].rs].fa = fa;
		return now;
	}
	
	inline int del(int tar) { 
		if(ns[tar].ls && ns[tar].rs) {//替换掉tar
			int tmp = find_del(ns[tar].rs);
			ns[tar].v = ns[tmp].v;
			ns[tmp].init();
			return tmp;
		} else {//直接删掉tar 
			int fa = ns[tar].fa;
			if(ns[tar].ls) {
				if(ns[fa].ls == tar) ns[fa].ls = ns[tar].ls;
				else ns[fa].rs = ns[tar].ls;
				ns[ns[tar].ls].fa = fa;
				if(fa == 0) root_ = ns[tar].ls;
			} else if(ns[tar].rs){
				if(ns[fa].ls == tar) ns[fa].ls = ns[tar].rs;
				else ns[fa].rs = ns[tar].rs;
				ns[ns[tar].rs].fa = fa;
				if(fa == 0) root_ = ns[tar].rs;
			} else {//叶子节点 
				if(ns[fa].ls == tar) ns[fa].ls = 0;
				else ns[fa].rs = 0;
				if(fa == 0) root_ = 0;
			}
			return tar;
		}
	}
	
	inline void change(int tar, int v) {
		int now = root_;
		while(true) { //找到位置 
			ns[now].size--;
			if(ns[now].v == tar) break;
			else if(tar < ns[now].v) now = ns[now].ls;
			else now = ns[now].rs;
		}
		int num = del(now); //删掉原来的数 
		insert(v, num); //插入新数 
	}
	
	inline int get_rank(int tar) {
		int ans = 0, now = root_;
		while(now) {
			if(ns[now].v < tar) ans += ns[ns[now].ls].size+1, now = ns[now].rs;
			else  now = ns[now].ls;
		}
		return ans;
	}
	
	inline int get_pre(int tar) {//找前驱 
		int ans = -inf, now = root_;
		while(now) {
			if(ns[now].v < tar) ans = max(ans, ns[now].v), now = ns[now].rs;
			else  now = ns[now].ls;
		}
		return ans;
	}
	
	inline int get_sux(int tar) {
		int ans = inf, now = root_;
		while(now) {
			if(ns[now].v > tar) ans = min(ans, ns[now].v), now = ns[now].ls;
			else  now = ns[now].rs;
		}
		return ans;
	}
	
	void print(int now) {
		if(ns[now].ls) print(ns[now].ls);
		printf("%d ",ns[now].v);
		if(ns[now].rs) print(ns[now].rs);
	}
	
	void out() {
		print(root_);
	}
}; 


class segment_tree {
private:
	struct snode {
		int l, r;
		treap t;
		snode() {}
		snode(int l_, int r_) { l = l_, r = r_, t = treap(); }
	}sns[maxn<<2];
	 
public:
	
	inline void build(int i, int l, int r) {
		if(l == r) {
			sns[i] = snode(l, r);
			sns[i].t.insert(a[l], ++tot);
//			printf("l = %d r = %d:\n", l, r);
//			sns[i].t.out();
//			printf("\n");
			return;
		}
		
		build(i << 1, l, (l+r) >> 1);//先处理根节点,这样可以保证子树连续 
		build ((i << 1) | 1, ((l+r) >> 1) + 1, r);
		
		sns[i] = snode(l, r);
		sns[i].t.copy(sns[i<<1].t.root(), sns[i<<1].t.size());//先拷贝左子节点 
		for(int j = ((l+r) >> 1) + 1; j <= r; j++) {//右半部分全部插入 
			sns[i].t.insert(a[j], ++tot);
		}
//		printf("l = %d r = %d:\n", l, r);
//		sns[i].t.out();
//		printf("\n");
	}
	
	inline void change(int tar, int v) {
		int i = 1;
		while(sns[i].l != sns[i].r) {
			sns[i].t.change(a[tar], v);
			if(tar <= sns[i<<1].r) i = (i << 1);
			else i = ((i << 1) | 1);
		}
		sns[i].t.change(a[tar], v);
	}
		
	int get_rank(int i, int l, int r, int num) {
		if(sns[i].l == l && sns[i].r == r) return sns[i].t.get_rank(num);

		if(sns[i<<1].r >= r) return get_rank(i<<1, l, r, num);
		else if(sns[(i<<1)|1].l <= l) return get_rank((i<<1)|1, l, r, num);
		else return get_rank(i<<1, l, sns[i<<1].r, num) + get_rank((i<<1)|1, sns[(i<<1)|1].l, r, num);
	}
	
	inline int get_num(int l, int r, int rank) {
		int bl = 0, br = inf;
		int mid;
		while(bl < br) {
			mid = (bl+br) >> 1;
			if(get_rank(1, l, r, mid) >= rank) br = mid;
			else  bl = mid+1;
		}
		return br-1;
	}
	
	inline int get_pre(int i, int l, int r, int num) {
		if(sns[i].l == l && sns[i].r == r) return sns[i].t.get_pre(num);

		if(sns[i<<1].r >= r) return get_pre(i<<1, l, r, num);
		else if(sns[(i<<1)|1].l <= l) return get_pre((i<<1)|1, l, r, num);
		else return max(get_pre(i<<1, l, sns[i<<1].r, num), get_pre((i<<1)|1, sns[(i<<1)|1].l, r, num));
	}
	
	inline int get_sux(int i, int l, int r, int num) {
		if(sns[i].l == l && sns[i].r == r) return sns[i].t.get_sux(num);

		if(sns[i<<1].r >= r) return get_sux(i<<1, l, r, num);
		else if(sns[(i<<1)|1].l <= l) return get_sux((i<<1)|1, l, r, num);
		else return min(get_sux(i<<1, l, sns[i<<1].r, num), get_sux((i<<1)|1, sns[(i<<1)|1].l, r, num));
	}
}st;

int get_num() {
	int ans = 0;
	int han = 1;
	char tmp = getchar();
	while(tmp < '0' || tmp > '9') {
		if(tmp == '-') han = -1;
		tmp = getchar();
	}
	while(tmp <= '9' && tmp >= '0') {
		ans = ans*10 + tmp - '0';
		tmp = getchar();
	}
	return ans*han;
} 

inline void read() {
	n = get_num();
	q = get_num();
	for(int i = 1; i <= n; i++) {
		a[i] = get_num();
	}
}

inline void solve() {
	st.build(1, 1, n);
	int han, l, r, k, tar;
	for(int i = 1; i <= q; i++) {
		han = get_num();
		if(han == 1) 	  { l = get_num(); r = get_num(); k = get_num(); printf("%d\n", st.get_rank(1, l, r, k)+1); }
		else if(han == 2) { l = get_num(); r = get_num(); k = get_num(); printf("%d\n", st.get_num(l, r, k)); }
		else if(han == 3) { tar = get_num(); k = get_num(); st.change(tar, k); a[tar] = k;}
		else if(han == 4) { l = get_num(); r = get_num(); k = get_num(); printf("%d\n", st.get_pre(1, l, r, k)); }
		else if(han == 5) { l = get_num(); r = get_num(); k = get_num(); printf("%d\n", st.get_sux(1, l, r, k)); }
	}
}

int main() {
	freopen("psh.in", "r", stdin);
	freopen("psh.out", "w", stdout);
	srand((unsigned)time(NULL));
	read();
	solve();
	return 0;
}