P3285 [SCOI2014]方伯伯的OJ

神仙题,让我学会了NEW东西。

考虑到人实在太多了,不能直接把编号记录下来。我们可以使用

动 态 开 点 \(s\ p\ l\ a\ y\)

具体地,splay的每一个结点存储一段编号连续的区间,splay的内部根据排名排序。

每一次询问拆点即可。

实现稍(fei)微(chang)麻烦一些。

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
#define orz cout<<"lyakioi!!!!!!!!!!!!!!!!!"<<endl
inline int r(){int s=0,k=1;char c=getchar();while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}while(isdigit(c)){s=s*10+c-'0';c=getchar();}return s*k;}
struct splay
{
	int fa,son[2],size,l,r,cnt,sum;
}a[1000001];
int root,n,times,lst,cnt;
map<int,int>m;
int get(int x)
{
	return x==a[a[x].fa].son[1];
}
void push_up(int x)
{
	if(!x)return;
	a[x].size=a[a[x].son[0]].size+a[a[x].son[1]].size+1;
	a[x].sum=a[a[x].son[0]].sum+a[a[x].son[1]].sum+a[x].cnt;
}
void rotate(int x)
{
	if(!x)return;
	int y=a[x].fa,z=a[y].fa;
	int i=get(x),j=get(y);
	a[z].son[j]=x;
	a[x].fa=z;
	a[y].son[i]=a[x].son[i^1];
	a[a[x].son[i^1]].fa=y;
	a[x].son[i^1]=y;
	a[y].fa=x;
	push_up(y);push_up(x);
}
void splay(int x,int goal)
{
	while(a[x].fa!=goal)
	{
		int y=a[x].fa,z=a[y].fa;
		if(z!=goal)
		{
			if(get(x)==get(y))rotate(y);
			else rotate(x);
		}
		rotate(x);
	}
	if(!goal)root=x;
}
int fd(int x)
{
	int now=root;
	while(1)
	{
		if(x<=a[a[now].son[0]].size)now=a[now].son[0];
		else if(x>a[a[now].son[0]].size+1)x-=a[a[now].son[0]].size+1,now=a[now].son[1];
		else return now;
	}
}
void insert_lst(int l,int r)
{
	int now=root,tmp=0;
	while(now)
	{
		tmp=now;
		now=a[now].son[1];
	}
	times++;cnt++;
	a[times].fa=tmp;
	a[times].l=l;
	a[times].r=r;
	a[times].cnt=r-l+1;
	a[times].size=1;
	m[r]=times;
	a[tmp].son[1]=times;
	splay(times,0);
}
void insert_kth(int l,int r,int k)//k为排名
{
//	cout<<"wow~"<<" "<<l<<" "<<r<<" "<<k<<endl;
	int x=fd(k-1),y=fd(k);
//	cout<<"can't find"<<x<<" "<<y<<endl;
	splay(x,0);
	splay(y,x);
	times++;cnt++;
	a[y].son[0]=times;
	a[times].fa=y;
	a[times].l=l;
	a[times].r=r;
	a[times].cnt=r-l+1;
	a[times].size=1;
	m[r]=times;
	splay(times,0);	
}
void erase(int now,int rank)
{
	cnt--;
	splay(now,0);
	int x=fd(rank),y=fd(rank+2);
	splay(x,0);
	splay(y,x);
	a[y].son[0]=0;
}
void dfs(int x)
{
	if(a[x].son[0])dfs(a[x].son[0]);
	cout<<a[x].l<<' '<<a[x].r<<endl;
	if(a[x].son[1])dfs(a[x].son[1]);
}
int fd_kth(int x)
{
	int now=root;
	while(1)
	{
		if(x<=a[a[now].son[0]].sum)now=a[now].son[0];
		else if(x>a[a[now].son[0]].sum+a[now].cnt)x-=a[a[now].son[0]].sum+a[now].cnt,now=a[now].son[1];
		else
		{
			x-=a[a[now].son[0]].sum+1;
			return a[now].l+x;
		}
	}
}
int main()
{
	int q;
	n=r();q=r();
	insert_lst(-1,-2);
	insert_lst(1,n);
	insert_lst(-3,-4);
	int opt,x,y;
//	dfs(root);
	for(int i=1;i<=q;i++)
	{
//		cout<<"=======================\n";
//		cout<<"i:"<<i<<endl;
//		dfs(root);
//		cout<<"\n";
		opt=r();
		if(opt==1)
		{
			x=r();y=r();
			x-=lst;y-=lst;
			int mid=x,tmp=1;
			x=(*m.lower_bound(x)).second;
			splay(x,0);
			int rank=a[a[x].son[0]].size;
			int le=a[x].l,ri=a[x].r;
			printf("%d\n",lst=a[a[x].son[0]].sum+mid-a[x].l+1);
			erase(x,rank);
//			cout<<"sb\n";
//			dfs(root);
//			puts("");
			if(le<mid)insert_kth(le,mid-1,rank+tmp),tmp++;
//			dfs(root);
			insert_kth(y,y,rank+tmp);tmp++;
			if(ri>mid)insert_kth(mid+1,ri,rank+tmp),tmp++;
		}
		if(opt==2)
		{
			x=r();x-=lst;
			int mid=x,tmp=1;
			x=(*m.lower_bound(x)).second;
			splay(x,0);
			int rank=a[a[x].son[0]].size;
			int le=a[x].l,ri=a[x].r;
			printf("%d\n",lst=a[a[x].son[0]].sum+mid-a[x].l+1);
			erase(x,rank);
			if(le<mid)insert_kth(le,mid-1,rank+tmp),tmp++;
			if(ri>mid)insert_kth(mid+1,ri,rank+tmp),tmp++;
			insert_kth(mid,mid,2);
		}
		if(opt==3)
		{
			x=r();x-=lst;
			int mid=x,tmp=1;
			x=(*m.lower_bound(x)).second;
			
//			cout<<"I GET "<<x<<endl;
			splay(x,0);
			int rank=a[a[x].son[0]].size;
			int le=a[x].l,ri=a[x].r;
//			cout<<"IT'S "<<le<<" "<<ri<<" "<<rank<<endl;
			printf("%d\n",lst=a[a[x].son[0]].sum+mid-a[x].l+1);
			erase(x,rank);
			if(le<mid)insert_kth(le,mid-1,rank+tmp),tmp++;
			if(ri>mid)insert_kth(mid+1,ri,rank+tmp),tmp++;
//			cout<<"BUT CNT IS"<<cnt<<endl;
			insert_kth(mid,mid,cnt);tmp++;
		}
		if(opt==4)
		{
			x=r();
			x-=lst;
			printf("%d\n",lst=fd_kth(x));
		}
	}
} 
posted @ 2021-09-03 18:09  lei_yu  阅读(32)  评论(0编辑  收藏  举报