原题跑的飞快的splay,t的只有52分了,求助大佬(急急急,跪谢
查看原帖
原题跑的飞快的splay,t的只有52分了,求助大佬(急急急,跪谢
877377
qzhfx楼主2023/9/9 13:38
#include<bits/stdc++.h>
#define endl '\n'
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
#define fa(x) t[x].fa
#define root t[0].ch[1]
using namespace std;
using ll = long long;
const int inf = (1<<30)+1;
struct node{
	int v;//权值;
	int fa;//父亲节点;
	int ch[2];//0,1分别代表左右儿子;
	int rec;//这个权值节点出现次数;
	int sum;//子节点数量
}t[2000100];
int tot;//tot表示不算重复的有多少节点;
bool ident(int x)//判断左右儿子;
{
	return t[t[x].fa].ch[0]==x?0:1;
}
int newnode(int v,int f){
	t[++tot].fa=f;
	t[tot].v=v;
	t[tot].sum=t[tot].rec=1;
	return tot;
}
void connect(int x,int fa,int how){
	
	t[fa].ch[how] = x;
	t[x].fa = fa;
}
void update(int x){
	if(x)
		t[x].sum=t[ls(x)].sum+t[rs(x)].sum+t[x].rec;
}
void rotate(int x){//x为新根;
	int Y = fa(x),R=fa(Y);
	int Yson=ident(x),Rson=ident(Y);
	connect(t[x].ch[Yson^1],Y,Yson);
	connect(Y,x,Yson^1);
	connect(x,R,Rson);
	update(Y);update(x);
}
void Splay(int x,int to){//将x搬至to;
	to = fa(to);
	while(fa(x)!=to){
		int y=fa(x);
		if(t[y].fa==to)rotate(x);
		else if(ident(x)==ident(y))
			rotate(y),rotate(x);
		else rotate(x),rotate(x);
	}
	
}
void Insert(int x){
	int now=root;
	if(root==0){newnode(x,0);root=tot;}
	else {
		while(1){
			t[now].sum++;
			if(t[now].v==x){
				t[now].rec++;
				Splay(now,root);
				return;
			}
			int nxt=x<t[now].v?0:1;
			if(!t[now].ch[nxt]){
				int p=newnode(x,now);
				t[now].ch[nxt]=p;
				Splay(p,root);
				return;
			}
			now=t[now].ch[nxt];
		}
	}
}
int find(int v){
	int now=root;
	while(1){
		if(!now)return 0;
		if(t[now].v==v){
			Splay(now,root);return now;
		}
		int nxt=v<t[now].v?0:1;
//		if(!t[now].ch[nxt])return 0;
		now=t[now].ch[nxt];
	}
}
void delet(int x){
	int pos=find(x);
	if(!pos)return;
	if(t[pos].rec>1){
		t[pos].rec--,t[pos].sum--;
		return;
	}else{
		if(!t[pos].ch[0]&&!t[pos].ch[1]){
			root=0;
			return;
		}else if(!t[pos].ch[0]){
			root=t[pos].ch[1];
			t[root].fa=0;
			return;
		}else {
			int left=t[pos].ch[0];
			while(t[left].ch[1])left=t[left].ch[1];
			Splay(left,t[pos].ch[0]);
			connect(t[pos].ch[1],left,1);
			connect(left,0,1);
			update(left);
		}
	}
}

int arank(int x){//查询排名为x的数;
	int now=root;
	while(1){
		int used=t[now].sum-t[t[now].ch[1]].sum;
		if(x>t[t[now].ch[0]].sum&&x<=used)break;
		if(x<used)now=t[now].ch[0];
		else x=x-used,now=t[now].ch[1];
	}
	Splay(now,root);
	return t[now].v;
}
int lower(int v)//小于v的最大值;
{
	int now=root;
	int ans=-inf;
	while(now){
		if(t[now].v<v)
			ans=max(t[now].v,ans);
		int nxt = v<=t[now].v?0:1;
		now=t[now].ch[nxt];
	}
	Splay(fa(now),root);
	return ans;
}

int upper(int x){//大于x最小的数;
	int now=root;
	int ans=inf;
	while(now){
		if(t[now].v>x) ans=min(ans,t[now].v);
		int nxt=x<t[now].v?0:1;
		now=t[now].ch[nxt];
	}
	Splay(fa(now),root);
	return ans;
}
int rak(int val)//查询x数的排名;
{
	int pos = find(val);
	if(!pos)return rak(upper(val));
	Splay(pos,root);
	return t[ls(pos)].sum+1;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		Insert(x);
	}
	int ans1=0,last=0,ans=0;
	while(m--){
		int op,x;
		cin>>op>>x;
		x^=last;
		
		if(op==1){
			Insert(x);
		}else if(op==2){
			delet(x);
		}else if(op==3){
			ans=rak(x);
		}else if(op==4){
			ans=arank(x);
		}else if(op==5){
			ans=lower(x);
		}else ans=upper(x);
		if(op>=3)last = ans;
		if(op>=3)ans1^=ans;
	}
	cout<<ans1<<endl;
	return 0;
}
2023/9/9 13:38
加载中...