记录编号 424085 评测结果 AAAAAAAAAA
题目名称 [TYVJ1730]二逼平衡树 最终得分 100
用户昵称 GravatarHzoi_Ivan 是否通过 通过
代码语言 C++ 运行时间 5.124 s
提交时间 2017-07-12 20:24:57 内存使用 1.27 MiB
显示代码纯文本
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#define inf 1e8
#define size(a) ((a!=NULL)?(a)->size:0)
using namespace std;
int n,m,a[50005];
 
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
 
struct node{
	int key,num,size,tot;
	node *ch[2];
	node(int x=0){
		key=rand();num=x;size=tot=1;
		memset(ch,0,sizeof ch);
	}
	void* operator new(size_t);
	void operator delete(void  *p);
}*root[200005],*C,*M;
 
vector<node*> q;
 
void* node :: operator new(size_t){
	node *p;
	if(!q.empty()){
		p=q.back();
		q.pop_back();
	}
	else {if(C==M){
			C=new node[1<<10];
			M=C+(1<<10);
		}p=C++;
	}
	return p;
}
 
void node :: operator delete(void *p){
	q.push_back((node*)p);
}
 
void pushup(node *now){
	if(!now) return ;
	now->size=size(now->ch[0])+size(now->ch[1])+now->tot;
}
 
void rot(node *&now,int wh){
	node *t=now->ch[wh];
	now->ch[wh]=t->ch[wh^1];
	t->ch[wh^1]=now;
	pushup(now);pushup(t);
	now=t;
}
 
void insert(node *&now,int x){
	if(!now){
		now=new node(x);
		return ;
	}
	if(now->num==x){now->tot++;now->size++;return;}
	int wh=now->num<x;
	insert(now->ch[wh],x);
	pushup(now); 
	if(now->ch[wh]->key<now->key) rot(now,wh);
}
 
void del(node *&now,int x){
	if(!now) return;
	if(now->num==x){
		if(now->tot>1){now->tot--;now->size--;return;}
		else if(now->ch[0]==NULL&&now->ch[1]==NULL){delete now;now=NULL;return;}
		else if(now->ch[0]==NULL){
			node *t=now;
			now=now->ch[1];
			delete t; t=NULL;
		}
		else if(now->ch[1]==NULL){
			node *t=now;
			now=now->ch[0];
			delete t; t=NULL;
		}
		else{
			int wh=now->ch[0]->key>now->ch[1]->key;
			rot(now,wh); del(now,x);
		}
	}
	else{
		if(now->num<x) del(now->ch[1],x);
		else del(now->ch[0],x);
	}
	if(now) pushup(now);
}
 
int rank(node *now,int x){
	int ans=0;
	while(now){
		if(now->num<x){
			ans+=size(now->ch[0])+now->tot;
			now=now->ch[1];
		}
		else if(now->num==x){ans+=size(now->ch[0]);break;}
		else now=now->ch[0];
	}
	return ans;
}
 
void build(int now,int l,int r,int pos,int x){
	insert(root[now],x);
	if(l==r) return ;
	int mid=(l+r)/2;
	if(pos<=mid) build(now<<1,l,mid,pos,x);
	else build(now<<1|1,mid+1,r,pos,x);
}
 
int getrank(int now,int l,int r,int x,int y,int pos){
	int ans=0;
	if(l>=x&&r<=y){
		ans+=rank(root[now],pos);
		return ans;
	}
	int mid=(l+r)/2;
	if(x<=mid) ans+=getrank(now<<1,l,mid,x,y,pos);
	if(y>mid) ans+=getrank(now<<1|1,mid+1,r,x,y,pos);
	return ans;
}
 
int getkth(int x,int y,int z){
	int l=0,r=inf,mid; z--;
    while(l+1<r){
        mid=(l+r)/2;
        if(getrank(1,1,n,x,y,mid)<=z) l=mid;
        else r=mid;
    }
    if(getrank(1,1,n,x,y,r)>z) return l;
    return r;
}
 
void update(int now,int l,int r,int pos,int x){
	del(root[now],a[pos]);
	insert(root[now],x);
	if(l==r) return ;
	int mid=(l+r)/2;
	if(pos<=mid) update(now<<1,l,mid,pos,x);
	else update(now<<1|1,mid+1,r,pos,x);
}
 
int getpre(int l,int r,int x){
	return getkth(l,r,getrank(1,1,n,l,r,x));
}
 
int getnext(int l,int r,int x){
	return getkth(l,r,getrank(1,1,n,l,r,x+1)+1);
}
int main()
{
	freopen("psh.in","r",stdin);
	freopen("psh.out","w",stdout);
	n=read(); m=read(); 
	srand(time(NULL));
	for(int i=1;i<=n;i++){
		a[i]=read();
		build(1,1,n,i,a[i]);
	}
	int opt,l,r,pos,x;
	while(m--){
		scanf("%d",&opt);
		switch(opt){
			case 1: l=read();r=read();x=read(); printf("%d\n",getrank(1,1,n,l,r,x)+1); break;
			case 2: l=read();r=read();x=read(); printf("%d\n",getkth(l,r,x)); break;
			case 3: pos=read();x=read(); if(a[pos]==x)break; update(1,1,n,pos,x); a[pos]=x; break;
			case 4: l=read();r=read();x=read(); printf("%d\n",getpre(l,r,x)); break;
			case 5: l=read();r=read();x=read(); printf("%d\n",getnext(l,r,x)); break;
		}
	}
	return 0;
}