[cf420D]Cup Trick(平衡树)

题目还是比较直接的。模拟一下过程然后发现,只要从后向前做,一开始每个节点都为0,每次找到第一个节点,标记为xi,把它从平衡树上分离,再插到第yi-1个节点后面即可。如果要标记的节点已经不为0,且不等于xi,输出-1;如果xi已经在平衡树中,且不是第一个节点,输出-1.

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000010;
struct opr{
	int x,y;
}q1[N];
struct node{
	int fa,l,r,siz,x;
}tree[N];
int n,m,num,num1,root,vis[N];
inline int read(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x;
}
inline void update(int p){
	tree[p].siz=1+tree[tree[p].l].siz+tree[tree[p].r].siz;
}
inline void left_rotate(int p){
	int q=tree[p].fa,r=tree[q].fa;
	tree[q].r=tree[p].l;
	if(tree[p].l)tree[tree[p].l].fa=q;
	tree[p].l=q,tree[q].fa=p;
	update(q),update(p);
	tree[p].fa=r;
	if(r){
		if(tree[r].l==q)tree[r].l=p;
		else tree[r].r=p;
	}
}
inline void right_rotate(int p){
	int q=tree[p].fa,r=tree[q].fa;
	tree[q].l=tree[p].r;
	if(tree[p].r)tree[tree[p].r].fa=q;
	tree[p].r=q,tree[q].fa=p;
	update(q),update(p);
	tree[p].fa=r;
	if(r){
		if(tree[r].l==q)tree[r].l=p;
		else tree[r].r=p;
	}
}
inline int getlr(int p){
	return tree[tree[p].fa].l==p;
}
inline void rotate(int p){
	if(getlr(p))right_rotate(p);
	else left_rotate(p);
}
inline void splay(int p,int tar){
	while(tree[p].fa!=tar&&tree[tree[p].fa].fa!=tar){
		if(getlr(p)==getlr(tree[p].fa))rotate(tree[p].fa),rotate(p);
		else rotate(p),rotate(p);
	}
	if(tree[p].fa!=tar)rotate(p);
	if(!tar)root=p;
}
int build(int a,int b){
	int p=++num;
	tree[p].x=tree[p].l=tree[p].r=tree[p].fa=0,tree[p].siz=b-a+1;
	if(a==b)return p;
	int mid=(a+b)>>1;
	if(a<mid){tree[p].l=build(a,mid-1);tree[tree[p].l].fa=p;}
	if(b>mid){tree[p].r=build(mid+1,b);tree[tree[p].r].fa=p;}
	return p;
}
void print(int p){
	if(tree[p].l)print(tree[p].l);
	if(!tree[p].x){
		while(vis[num1])++num1;
		tree[p].x=num1,vis[num1]=1;
	}
	printf("%d ",tree[p].x);
	if(tree[p].r)print(tree[p].r);
}
int getkth(int k){
	int p=root,p1;
	while(1){
		if(tree[tree[p].l].siz>=k)p=tree[p].l;
		else if(tree[tree[p].l].siz+1==k)break;
		else k-=tree[tree[p].l].siz+1,p=tree[p].r;
	}
	splay(p,0);p1=tree[p].r;
	if(p1){
		while(tree[p1].l)p1=tree[p1].l;
		splay(p1,p);
	}
	return p;
}
int main(){
	n=read(),m=read(),num=0;
	if(n==1){printf("1");return 0;}
	memset(vis,0,sizeof vis);
	for(int i=0;i<m;++i)q1[m-i].x=read(),q1[m-i].y=read();
	root=build(1,n);tree[0].fa=tree[0].x=tree[0].l=tree[0].r=tree[0].siz=0;
	for(int i=1,p1,p2;i<=m;++i){
		p1=getkth(1);
		if(tree[p1].x==0){
			if(vis[q1[i].x]){printf("-1");return 0;}
			tree[p1].x=q1[i].x;vis[q1[i].x]=1;
		}
		if(tree[p1].x!=q1[i].x){printf("-1");return 0;}
		if(q1[i].y==1)continue;
		root=tree[p1].r,tree[tree[p1].r].fa=0,tree[p1].r=0,tree[p1].siz=1;
		p2=getkth(q1[i].y-1);
		if(tree[root].r){
			tree[tree[root].r].l=p1,tree[p1].fa=tree[root].r,
			update(tree[root].r),update(root);
		}else{
			tree[root].r=p1,tree[p1].fa=root;update(root);
		}
	}
	num1=1;print(root);
	return 0;
} 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值