记录编号 99608 评测结果 AAAAAAAAAA
题目名称 [TYVJ1730]二逼平衡树 最终得分 100
用户昵称 GravatarOI永别 是否通过 通过
代码语言 C++ 运行时间 3.208 s
提交时间 2014-04-28 21:18:33 内存使用 40.37 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 1050010
struct arr{
	int l,r,root;
}t[N];
struct aerr{
	int l,r,dat,ran;
	int ll,rr;
}t1[N];
int n,m;
int a[N];
int size = 0;
bool flag = 0;
void read(int &x){
	bool hx=0;
	char ch;
	while ((ch=getchar())&& (ch>'9' || ch<'0')){
		if (ch=='-')hx=1;
	};
	x=ch-'0';
	while ((ch=getchar())&& (ch<='9' && ch>='0'))x=x*10+ch-'0';
	if (hx)x=-x;
}
void right(int &x){
	int tem = t1[x].r;
	t1[x].r = t1[tem].l;
	t1[tem].l = x;
	t1[x].rr = t1[tem].ll;
	t1[tem].ll = t1[x].ll + t1[x].rr + 1;
	x = tem;
	return;
}

void left(int &x){
	int tem = t1[x].l;
	t1[x].l = t1[tem].r;
	t1[tem].r = x;
	t1[x].ll = t1[tem].rr;
	t1[tem].rr = t1[x].ll + t1[x].rr + 1;
	x = tem;
	return;
}

void insert(int & x,int y){
	if (!x){
		x = ++size;
		t1[x].l = t1[x].r = 0;
		t1[x].ll = t1[x].rr = 0;
		t1[x].dat = y;
		t1[x].ran = rand()*rand();
	}
	else{
		if (y >= t1[x].dat){
			insert(t1[x].r,y);
			t1[x].rr ++;
			if (t1[x].ran > t1[t1[x].r].ran) right(x);
		}
		else{
			insert(t1[x].l,y);
			t1[x].ll ++;
			if (t1[x].ran > t1[t1[x].l].ran) left(x);
		}
	}
	return;
}


void build(int p,int l,int r){
	t[p].l = l,t[p].r = r;
	if (l == r){
		insert(t[p].root,a[l]);
		return;
	}
	for (int i = l; i <= r; i++){
		insert(t[p].root,a[i]);
	}
	int mid = (l + r) >> 1;
	build(p << 1,l,mid);
	build((p << 1)+ 1,mid + 1,r);
	return;
}

int ask(int x,int y){
	if (! x) return 0;
	if (t1[x].dat == y) {
		flag = 1;
	}
	if (t1[x].dat >= y){
		return ask(t1[x].l,y);
	}
	else return t1[x].ll + 1 + ask(t1[x].r,y);
}

int asknum(int p,int x,int y,int z){
	if (t[p].l >= x && t[p].r <= y){
		int tem;
		tem = ask(t[p].root,z);
		return tem;
	}
	int mid = (t[p].l + t[p].r) >> 1;
	int ans = 0;
	if (mid >= x) ans += asknum(p << 1,x,y,z);
	if (mid < y) ans += asknum((p << 1) + 1,x,y,z);
	return ans;
}

int askrank(int p,int x,int y,int z){
	int tt = t[p].root;
	flag = 0;
	int ans;
	int tem = asknum(1,x,y,t1[tt].dat) + 1;
	while (tt){
		if (tem <= z){
			if (flag) ans = t1[tt].dat;	
			if (tem == z && flag) break;
			if (tt != t1[tt].r){
				flag = 0;
				tem = asknum(1,x,y,t1[t1[tt].r].dat) + 1;
			}
			tt = t1[tt].r;
		}
		else{
			if (tt != t1[tt].l){
				flag = 0;
				tem = asknum(1,x,y,t1[t1[tt].l].dat) + 1;
			}
			tt = t1[tt].l;
		}
	}
	return ans;
}

void del(int &x,int y){
	if (t1[x].dat == y){
		if (t1[x].l == 0 || t1[x].r == 0){
			if (t1[x].l == 0){
				x = t1[x].r;
				return;
			}
			if (t1[x].r == 0){
				x = t1[x].l;
				return;
			}
		}
		else{
			if (t1[t1[x].l].ran >= t1[t1[x].r].ran){
				right(x);
				t1[x].ll--;
				del(t1[x].l,y);
			}
			else{
				left(x);
				t1[x].rr --;
				del(t1[x].r,y);
			}
		}
	}
	else{
		if (t1[x].dat < y) {
			t1[x].rr --;
			del(t1[x].r,y);
		}
		else{
			t1[x].ll --;
			del(t1[x].l,y);
		}
	}
}


void change(int p,int x,int y){
	if (t[p].l == t[p].r){
		del(t[p].root,t1[t[p].root].dat);
		insert(t[p].root,y);
		return;
	}
	del(t[p].root,a[x]);
	insert(t[p].root,y);
	int mid = (t[p].l + t[p].r) >> 1;
	if (x <= mid) change(p << 1,x,y);
	if (x > mid) change((p << 1)+ 1,x,y);
	return;
}

int pre(int x,int y){
	if (! x) return y;
	int ans = 0;
	if (y <= t1[x].dat) ans = pre(t1[x].l,y);
	else{
		ans = pre(t1[x].r,y);
		if (ans == y) ans = t1[x].dat;
	}
	return ans;
}

int askpre(int p,int x,int y,int z){
	if (t[p].l >= x && t[p].r <= y){
		int tem =  pre(t[p].root,z);
		if (tem == z) tem = -0x3f;
		return tem;
	}
	int ans = -0x3f,mid = (t[p].l + t[p].r) >> 1;
	if (x <= mid) ans = max(ans,askpre(p << 1,x,y,z));
	if (y > mid) ans = max(ans,askpre((p << 1) + 1,x,y,z));
	if (ans == z) ans = -0x3f;
	return ans;	
}

int succ(int x,int y){
	if (!x) return y;
	int ans = 0;
	if (y >= t1[x].dat) ans = succ(t1[x].r,y);
	else{
		ans = succ(t1[x].l,y);
		if (ans == y) ans = t1[x].dat;
	}
	return ans;
}

int asksucc(int p,int x,int y,int z){
	if (t[p].l >= x && t[p].r <= y){
		int tem = succ(t[p].root,z);
		if (tem == z) tem = 0x7fffffff;
		return tem;
	}
	int ans = 0x7fffffff,mid = (t[p].l + t[p].r) >> 1;
	if (x <= mid) ans = min(ans,asksucc(p << 1,x,y,z));
	if (y > mid) ans = min(ans,asksucc((p << 1)+1,x,y,z));
	if (ans == z) ans = 0x7fffffff;
	return ans;	
} 

int main(){
	freopen("psh.in","r",stdin);
	freopen("psh.out","w",stdout);
	read(n);read(m);
	for (int i = 1; i <= n; i++) read(a[i]);//scanf("%d",&a[i]);
	build(1,1,n);
	int cc,x,y,z;
	while (m--){
		scanf("%d",&cc);
		switch (cc){
			case 1:{
				read(x);read(y);read(z);
				//scanf("%d%d%d",&x,&y,&z);
				int ans = asknum(1,x,y,z);
				printf("%d\n",ans + 1);
				break;
			}
			case 2:{
				read(x);read(y);read(z);
				//scanf("%d%d%d",&x,&y,&z);
				int ans = askrank(1,x,y,z);
				printf("%d\n",ans);
				break;
			}
			case 3:{
				read(x);read(z);
			//	scanf("%d%d",&x,&z);
				change(1,x,z);
				a[x] = z;
				break;
			}
			case 4:{
				read(x);read(y);read(z);
			//	scanf("%d%d%d",&x,&y,&z);
				int ans = askpre(1,x,y,z);
				printf("%d\n",ans);
				break;
			}
			case 5:{
				read(x);read(y);read(z);
				//scanf("%d%d%d",&x,&y,&z);
				int ans = asksucc(1,x,y,z);
				printf("%d\n",ans);
				break;
			}
		}
	}
	return 0;
}