http://www.lydsy.com/JudgeOnline/problem.php?id=3595
终于做了一道方伯伯系列了,在我还年轻的时候,我还分不清线段树和平衡树呢、、、貌似写了个暴力骗了10分。?
几次没有改调试输出,wa率瞬间被我拉高了
这道题开始看简直没思路,双关键字的平衡树。。。。。?
后来发现这个编号简直没用,才算把题意弄清楚,随便写了treap,A了
值得注意的是细节有点多尤其是关于区间大小的计算,很容易手抖。
Orz写动态开点线段树的
Orz写fhqTreap+SBT的
//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
/************************************************
Code By willinglive Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int getint()
{
int r=0,k=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
return k*r;
}
/
int n,m;
struct data{int l,r,s,rnd,index,ll,rr;}T[3000010];
int root,sz;
map<int,int>M1;
int mmin,mmax;
/
#define LS T[o].l
#define RS T[o].r
int rnd(){return rand()<<16|rand();}
void update(int o){T[o].s=T[LS].s+T[RS].s+T[o].rr-T[o].ll+1;}
void l_rot(int &o){int t=RS;RS=T[t].l;T[t].l=o;T[t].s=T[o].s;update(o);o=t;}
void r_rot(int &o){int t=LS;LS=T[t].r;T[t].r=o;T[t].s=T[o].s;update(o);o=t;}
void insert(int &o,int index,int ll,int rr)
{
if(!o)
{
o=++sz; T[o].s=rr-ll+1; T[o].rnd=rnd(); T[o].index=index; T[o].ll=ll; T[o].rr=rr;
return;
}
T[o].s+=rr-ll+1;
if(ll<T[o].ll)
{
insert(LS,index,ll,rr);
if(T[LS].rnd<T[o].rnd) r_rot(o);
}
else
{
insert(RS,index,ll,rr);
if(T[RS].rnd<T[o].rnd) l_rot(o);
}
}
void del(int &o,int pos,int sz)
{
if(!o) return;
if(T[o].ll==pos)
{
if(LS==0||RS==0) o=LS+RS;
else if(T[LS].rnd<T[RS].rnd) r_rot(o),del(o,pos,sz);
else l_rot(o),del(o,pos,sz);
return;
}
T[o].s-=sz;
if(pos<T[o].ll) del(LS,pos,sz);
else del(RS,pos,sz);
}
void split(int o,int pos)
{
if(!o) return;
if(T[o].ll<=pos && pos<=T[o].rr)
{
if(T[o].ll==T[o].rr) del(root,pos,1);
else
{
del(root,T[o].ll,T[o].rr-T[o].ll+1);
if(T[o].ll<=pos-1) insert(root,T[o].ll,T[o].ll,pos-1);
if(pos+1<=T[o].rr) insert(root,pos+1,pos+1,T[o].rr);
}
return;
}
if(pos<T[o].ll) split(LS,pos);
else split(RS,pos);
}
int getrank(int o,int x)
{
if(!o) return 0;
if(T[o].ll<=x && x<=T[o].rr)
return T[LS].s+x-T[o].ll+1;
if(x<T[o].ll) return getrank(LS,x);
else return T[LS].s+T[o].rr-T[o].ll+1+getrank(RS,x);
}
int getindex(int o,int x)
{
if(!o) return 0;
if(x>T[LS].s && x<=T[LS].s+T[o].rr-T[o].ll+1)
{
if(T[o].ll==T[o].rr) return T[o].index;
else return T[o].ll+x-1-T[LS].s;
}
if(x<=T[LS].s)
return getindex(LS,x);
else
return getindex(RS,x-T[LS].s-(T[o].rr-T[o].ll+1));
}
/
void input()
{
n=getint(); m=getint();
}
void solve()
{
int a=0,op,x,y;
insert(root,1,1,n);
mmin=0; mmax=n;
while(m--)
{
//a=0;
op=getint(); x=getint(); x-=a;
if(op==1)
{
y=getint(); y-=a;
int tmp=M1[x];
if(!tmp) tmp=x;
printf("%d\n",a=getrank(root,tmp));
M1[y]=tmp;
M1[x]=0;
split(root,tmp);
insert(root,y,tmp,tmp);
}
else if(op==2)
{
int tmp=M1[x];
if(!tmp) tmp=x;
printf("%d\n",a=getrank(root,tmp));
split(root,tmp);
tmp=--mmin; M1[x]=tmp;
insert(root,x,tmp,tmp);
}
else if(op==3)
{
int tmp=M1[x];
if(!tmp) tmp=x;
printf("%d\n",a=getrank(root,tmp));
split(root,tmp);
tmp=++mmax; M1[x]=tmp;
insert(root,x,tmp,tmp);
}
else
{
printf("%d\n",a=getindex(root,x));
}
}
}
/
int main()
{
#ifndef _TEST
freopen("std.in","r",stdin); freopen("std.out","w",stdout);
#endif
input(),
solve();
return 0;
}