您的位置:首页 > 其它

NKOJ 4340 (SCOI 2014)方伯伯的OJ (Splay+map+set)

2017-12-01 22:52 483 查看

P4340【SCOI2014】方伯伯的Oj

问题描述



输入格式

输入的第1行包含2个用空格分隔的整数n和m,表示初始用户数和操作数。

此后有m行,每行是一个询问,询问格式如上所示。

输出格式

输出包含m行。每行包含一个整数,其中第i行的整数表示第i个操作的输出。

样例输入

10 10

1 2 11

3 13

2 5

3 7

2 8

2 10

2 11

3 14

2 18

4 9

样例输出

2

2

2

4

3

5

5

7

8

11

提示

对于 100% 的数据,1 ≤ n ≤ 10^8,1 ≤ m ≤ 10^5

输入保证对于所有的操作 1,2,3,x 必然已经出现在队列中,同时对于所有操作 1,1 ≤ y ≤ 2 × 10^8,并且

y 没有出现在队列中。

对于所有操作 4,保证 1 ≤ k ≤ n。

此题强制在线,观察发现n很大,那么显然此题应该根据m入手,考虑将Splay中的点维护一个区间,然后查询到了再拆开成3个点。

需要维护两个值,编号和排名,按照排名建立Splay,用map记录编号区间为[a,b]的点,还需要记录当前已经被拆过的点即查找过的位置,这样就可以通过编号找到在Splay中对应的位置,然后还需要开一个map记录表示一个点的点。

然后每种操作找到对应的Splay的位置,拆点后直接处理即可。

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<set>
#define N 1000005
using namespace std;
struct node
{
int l,r;
bool operator<(const node &b)const
{
if(l==b.l)return r<b.r;
return l<b.l;
}
};
set<int>A;
map<int,int>C;
map<node,int>B;
set<int>::iterator Ai;
map<node,int>::iterator Bi;
int n,m;
int rt,ls
,rs
,fa
,id
,lid
,rid
,v
,si
,tot;
void MT(int x)
{si[x]=si[ls[x]]+si[rs[x]]+v[x];}
void Zig(int x)
{
int y=fa[x],z=fa[y];
if(z)y==ls[z]?ls[z]=x:rs[z]=x;fa[x]=z;
ls[y]=rs[x];fa[rs[x]]=y;
rs[x]=y;fa[y]=x;
MT(y);MT(x);
}
void Zag(int x)
{
int y=fa[x],z=fa[y];
if(z)y==ls[z]?ls[z]=x:rs[z]=x;fa[x]=z;
rs[y]=ls[x];fa[ls[x]]=y;
ls[x]=y;fa[y]=x;
MT(y);MT(x);
}
void Splay(int x)
{
int y,z;
while(fa[x])
{
y=fa[x],z=fa[y];
if(z)
{
if(y==ls[z])x==ls[y]?(Zig(y),Zig(x)):(Zag(x),Zig(x));
else x==rs[y]?(Zag(y),Zag(x)):(Zig(x),Zag(x));
}
else x==ls[y]?Zig(x):Zag(x);
}
rt=x;
}
int Gmax(int p)
{
while(rs[p])p=rs[p];
return p;
}
int Gmin(int p)
{
while(ls[p])p=ls[p];
return p;
}
int Find(int x)
{
node tmp;
if(C.count(x))return C[x];
Ai=A.lower_bound(x);
tmp.r=*Ai-1;Ai--;
tmp.l=*Ai+1;
Bi=B.lower_bound(tmp);
return Bi->second;
}
int Div(int p,int x)
{
int l,r;node tmp;
Splay(p);
A.insert(x);
l=ls[p];r=rs[p];
fa[l]=fa[r]=ls[p]=rs[p]=0;
if(lid[p]<x-1)
{
tot++;
lid[tot]=lid[p];
rid[tot]=x-1;
v[tot]=x-lid[p];
fa[l]=tot;ls[tot]=l;
MT(tot);l=tot;
tmp.l=lid[l];
tmp.r=rid[l];
B[tmp]=l;
}
else if(lid[p]==x-1)
{
tot++;
id[tot]=lid[p];
v[tot]=1;
fa[l]=tot;
ls[tot]=l;
MT(tot);l=tot;
C[lid[p]]=tot;
}
if(x+1<rid[p])
{
tot++;
lid[tot]=x+1;
rid[tot]=rid[p];
v[tot]=rid[p]-x;
fa[r]=tot;rs[tot]=r;
MT(tot);r=tot;
tmp.l=lid[r];
tmp.r=rid[r];
B[tmp]=r;
}
else if(x+1==rid[p])
{
tot++;
id[tot]=x+1;
v[tot]=1;
fa[r]=tot;rs[tot]=r;
MT(tot);r=tot;
C[x+1]=tot;
}
fa[l]=fa[r]=++tot;
ls[tot]=l;rs[tot]=r;
id[tot]=x;v[tot]=1;
C[x]=tot;MT(tot);
return rt=tot;
}
void Del(int p)
{
int l=ls[p],r=rs[p];
fa[l]=fa[r]=ls[p]=rs[p]=0;
if(!l)rt=r;
else
{
l=Gmax(l);
Splay(l);
fa[r]=l;rs[l]=r;
rt=l;MT(l);
}
}
int Gkth(int k)
{
int p=rt;
while(p)
{
if(si[ls[p]]<k&&si[ls[p]]+v[p]>=k)return p;
if(si[ls[p]]>=k)p=ls[p];
else k-=si[ls[p]]+v[p],p=rs[p];
}
return p;
}
int main()
{
int i,j,k,x,y,z,p,l,r,t;node tmp;
scanf("%d%d",&n,&m);int ans=0;
rt=++tot;lid[rt]=1;rid[rt]=n;v[rt]=si[rt]=n;
A.insert(0);A.insert(n+1);
tmp.l=1;tmp.r=n;B[tmp]=rt;
while(m--)
{
scanf("%d",&k);
if(k==1)
{
scanf("%d%d",&x,&y);
x-=ans;y-=ans;p=Find(x);
if(v[p]==1)
{
id[p]=y;C[y]=p;Splay(p);
ans=si[ls[p]]+1;
printf("%d\n",ans);
}
else
{
p=Div(p,x);id[p]=y;C[y]=p;
ans=si[ls[p]]+1;
printf("%d\n",ans);
}
}
if(k==2)
{
scanf("%d",&x);
x-=ans;p=Find(x);
if(v[p]==1)
{
Splay(p);
ans=si[ls[p]]+1;
printf("%d\n",ans);
Del(p);rs[p]=rt;fa[rt]=p;rt=p;
}
else
{
p=Div(p,x);
ans=si[ls[p]]+1;
printf("%d\n",ans);
Del(p);rs[p]=rt;fa[rt]=p;rt=p;
}
}
if(k==3)
{
scanf("%d",&x);
x-=ans;p=Find(x);
if(v[p]==1)
{
Splay(p);
ans=si[ls[p]]+1;
printf("%d\n",ans);
Del(p);ls[p]=rt;fa[rt]=p;rt=p;
}
else
{
p=Div(p,x);
ans=si[ls[p]]+1;
printf("%d\n",ans);
Del(p);ls[p]=rt;fa[rt]=p;rt=p;
}
}
if(k==4)
{
scanf("%d",&x);
x-=ans;p=Gkth(x);Splay(p);
if(v[p]==1)ans=id[p],printf("%d\n",ans);
else
{
t=x-si[ls[p]];
x=lid[p]+t-1;
p=Div(p,x);
ans=id[p];
printf("%d\n",ans);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: