数据范围
n<=108,m<=105
n
<=
10
8
,
m
<=
10
5
一眼平衡树。5分钟出思路,调了3小时。
我们不好直接维护排名的平衡树,也不好直接维护编号的平衡树。
那就建
2
2
颗平衡树,一棵以编号中序遍历,一棵以排名中序遍历,每个节点开记录下这排名和编号。
然后对于每个操作 直接按照题意去修改就好了。把连续的区间缩成点用的时候再拆开。
注意以编号中序遍历中
pair
p
a
i
r
的排名并不是真实排名而是相对排名,需要到另一棵树中再查找。
findsz
f
i
n
d
s
z
操作中如果要找的点被那段区间包含了 就直接强行
split
s
p
l
i
t
拆开返回
sz
s
z
。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+5;
typedef pair<int,int>par;
#define mp make_pair
struct treap{
par val[MAXN];
int prio[MAXN],size[MAXN],lson[MAXN],rson[MAXN],lm[MAXN],rm[MAXN],rt,cnt;
inline int get(int p){
return rm[p]-lm[p]+1;
}
inline void pushup(int p){
size[p]=size[lson[p]]+size[rson[p]]+get(p);
}
inline int newnode(int l,int r){
++cnt;
if(l==r)val[cnt].first=l,val[cnt].second=l;
prio[cnt]=rand();size[cnt]=1;
lson[cnt]=rson[cnt]=0;lm[cnt]=l,rm[cnt]=r;
return cnt;
}
par split(int p,int x){
if(!x)return mp(0,p);
int l=lson[p],r=rson[p];
if(x<=size[l]){
par tem=split(l,x);
lson[p]=tem.second;pushup(p);return mp(tem.first,p);
}
else if(x>=size[l]+get(p)){
par tem=split(r,x-size[l]-get(p));
rson[p]=tem.first;pushup(p);return mp(p,tem.second);
}
x-=size[l];
int tem=rm[p];rm[p]=lm[p]+x-1;
if(rm[p]==lm[p])val[p]=mp(lm[p],lm[p]);
int pp=newnode(rm[p]+1,tem);
pp=merge(pp,r);rson[p]=0;
pushup(p);pushup(pp);
return mp(p,pp);
}
int merge(int x,int y){
if(!x){pushup(y);return y;}
if(!y){pushup(x);return x;}
if(prio[x]<prio[y]){
rson[x]=merge(rson[x],y);pushup(x);return x;
}
lson[y]=merge(x,lson[y]);pushup(y);return y;
}
int Split(int p,int v,int posp){
int l=lm[p],r=rm[p],sz=v-l;
par t1=split(rt,posp+sz);
par t2=split(t1.second,1);
rt=merge(t1.first,merge(t2.first,t2.second));
return posp+sz;
}
int findsz(int x){
int p=rt,sz=0;
while(p){
if(rm[p]>=x&&lm[p]<=x&&rm[p]-lm[p])
return size[lson[p]]+Split(p,x,sz);
if(rm[p]-lm[p]==0){//对于单个点
if(val[p].first==x)return size[lson[p]]+sz;
if(val[p].first>x)p=lson[p];
else sz+=size[lson[p]]+get(p),p=rson[p];
}
else {//区间
if(rm[p]>x)p=lson[p];
else sz+=size[lson[p]]+get(p),p=rson[p];
}
}
return sz;
}
void debug(int p){
if(lson[p])debug(lson[p]);
printf("%d ",val[p].second);
if(rson[p])debug(rson[p]);
}
}T[2];
int n,m,minn=0,maxx;
int change(int x,int y){
int pos=T[0].findsz(x);
par t1=T[0].split(T[0].rt,pos);
par t2=T[0].split(t1.second,1);
T[0].val[t2.first].first=y;
int ret=T[0].val[t2.first].second;
int put=T[1].findsz(ret)+1;
printf("%d\n",put);
T[0].rt=T[0].merge(t1.first,t2.second);
int pos2=T[0].findsz(y);
t1=T[0].split(T[0].rt,pos2);
T[0].rt=T[0].merge(t1.first,T[0].merge(t2.first,t1.second));
t1=T[1].split(T[1].rt,put-1);
t2=T[1].split(t1.second,1);
T[1].val[t2.first].second=y;
T[1].rt=T[1].merge(t1.first,T[1].merge(t2.first,t2.second));
return put;
}
int up(int x){
int pos=T[0].findsz(x);
par t1=T[0].split(T[0].rt,pos);
par t2=T[0].split(t1.second,1);
int ret=T[0].val[t2.first].second;
int put=T[1].findsz(ret)+1;
printf("%d\n",put);
T[0].val[t2.first].second=--minn;
T[0].rt=T[0].merge(t1.first,T[0].merge(t2.first,t2.second));
t1=T[1].split(T[1].rt,put-1);
t2=T[1].split(t1.second,1);
T[1].val[t2.first].first=minn;
T[1].rt=T[1].merge(t2.first,T[1].merge(t1.first,t2.second));
return put;
}
int down(int x){
int pos=T[0].findsz(x);
par t1=T[0].split(T[0].rt,pos);
par t2=T[0].split(t1.second,1);
int ret=T[0].val[t2.first].second;
int put=T[1].findsz(ret)+1;
printf("%d\n",put);
T[0].val[t2.first].second=++maxx;
T[0].rt=T[0].merge(t1.first,T[0].merge(t2.first,t2.second));
t1=T[1].split(T[1].rt,put-1);
t2=T[1].split(t1.second,1);
T[1].val[t2.first].first=maxx;
T[1].rt=T[1].merge(t1.first,T[1].merge(t2.second,t2.first));
return put;
}
int query(int x){
int p=T[1].rt,ans=0;
while(p){
if(ans+T[1].size[T[1].lson[p]]+T[1].get(p)<x){
ans+=T[1].size[T[1].lson[p]]+T[1].get(p);
p=T[1].rson[p];
}
else if(ans+T[1].size[T[1].lson[p]]>=x)
p=T[1].lson[p];
else {
if(T[1].rm[p]==T[1].lm[p]){
printf("%d\n",T[1].val[p].second);
return T[1].val[p].second;
}
else {
x-=ans+T[1].size[T[1].lson[p]];
printf("%d\n",T[1].lm[p]+x-1);
return T[1].lm[p]+x-1;
}
}
}
}
int main(){
int x,y;
scanf("%d%d",&n,&m);
minn=0,maxx=n+1;
T[0].rt=T[0].newnode(1,n);T[1].rt=T[1].newnode(1,n);
int pre=0;
for(int i=1;i<=m;i++){
int opt;
scanf("%d",&opt);
if(opt==1){
scanf("%d%d",&x,&y);
pre=change(x-pre,y-pre);
// T[1].debug(T[1].rt);puts("one");
}
else if(opt==2){
scanf("%d",&x);
// T[1].debug(T[1].rt);puts("s");
pre=up(x-pre);
}
else if(opt==3){
scanf("%d",&x);
pre=down(x-pre);
// T[1].debug(T[1].rt);puts("the");
// puts("vvv");T[0].debug(T[0].rt);
// puts("ggg");
}
else {
scanf("%d",&x);
pre=query(x-pre);
}
}
return 0;
}
/*
10 10
1 2 11
3 13
2 5
3 7
2 8
2 10
2 11
3 14
2 18
4 9
*/