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));
}
}
}
本文来自博客园,作者:lei_yu,转载请注明原文链接:https://www.cnblogs.com/lytql/p/15224306.html