[bzoj3224]普通平衡树
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[100004],ch[100004][2],key[100004],cnt[100004],size[100004],sz,root;
int n,opt,num;
void clean(int x){//清空
ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=size[x]=0;
}
int get(int x){//判断当前点是左还是右
return ch[f[x]][1]==x;//??????
}
void update(int x){//更新size值
if(x){
size[x]=cnt[x];
if(ch[x][0])size[x]+=size[ch[x][0]];
if(ch[x][1])size[x]+=size[ch[x][1]];
}
return;
}
void rotate(int x){
int old=f[x];
int oldf=f[old];
int p=get(x);
ch[old][p]=ch[x][p^1];
f[ch[old][p]]=old;
f[old]=x;
ch[x][p^1]=old;
f[x]=oldf;
if(oldf) ch[oldf][ch[oldf][1]==old]=x;
update(old);
update(x);
}
void splay(int x){
for(int fa;fa=f[x];rotate(x))
if(f[fa])rotate((get(x)==get(fa)?fa:x));
root=x;
}
int find(int v){//查询某数的排名
int ans=0;
int now=root;
while(1){
if(v<key[now]){
now=ch[now][0];
}
else{
ans+=(ch[now][0]?size[ch[now][0]]:0);
if(v==key[now]){
splay(now);
return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
int findx(int x){//查找排名为x的数
int now=root;
while(1){
if(ch[now][0]&&x<=size[ch[now][0]]) now=ch[now][0];
else{
int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
if(x<=temp) return key[now];
x-=temp;
now=ch[now][1];
}
}
}
int pre(){
int now=ch[root][0];
while(ch[now][1]) now=ch[now][1];
return now;
}
int sub(){
int now=ch[root][1];
while(ch[now][0]) now=ch[now][0];
return now;
}
void del(int x){
int whatever=find(x);
if(cnt[root]>1){
cnt[root]--;
return;
}
if(!ch[root][0]&&!ch[root][1]){
clean(root);
root=0;
return;
}
if(!ch[root][0]){
int oldroot=root;
root=ch[root][1];
f[root]=0;
clean(oldroot);
return;
}
else if(!ch[root][1]){
int oldroot=root;
root=ch[root][0];
f[root]=0;
clean(oldroot);
return;
}
int leftbig=pre();
int oldroot=root;
splay(leftbig);
f[ch[oldroot][1]]=root;
ch[root][1]=ch[oldroot][1];
clean(oldroot);
update(root);
return;
}
void insert(int v){
if(!root){
sz++;
ch[sz][0]=ch[sz][1]=f[sz]=0;
key[sz]=v;
cnt[sz]=1;
size[sz]=1;
root=sz;
return;
}
int now=root;
int fa=0,p;
while(1){
if(key[now]==v){
cnt[now]++;
update(fa);
splay(now);
break;
}
fa=now;p=(key[now]<v);
now=ch[now][p];
if(now==0){
sz++;
ch[sz][0]=ch[sz][1]=0;
f[sz]=fa;
key[sz]=v;
cnt[sz]=1;
ch[fa][p]=sz;
update(fa);
splay(sz);
break;
}
}
return;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&opt,&num);
if(opt==1)insert(num);
if(opt==2)del(num);
if(opt==3)printf("%d\n",find(num));
if(opt==4)printf("%d\n",findx(num));
if(opt==5){
insert(num);
printf("%d\n",key[pre()]);
del(num);
}
if(opt==6){
insert(num);
printf("%d\n",key[sub()]);
del(num);
}
}
return 0;
}
splay区间翻转
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#define ll long long
using namespace std;
int m,n,sz,rt,F[100004],s[100004][4],sit[100004],size[100004];
bool tip[100004];
void up(int k){size[k]=size[s[k][0]]+size[s[k][1]]+1;}
void down(int k){
int l=s[k][0],r=s[k][1];
if(tip[k]){
swap(s[k][0],s[k][1]);
tip[l]^=1;tip[r]^=1;tip[k]=0;
}
}
void rote(int x,int &k){
int y=F[x],z=F[y],l,r;
if(s[y][0]==x)l=0;else l=1;r=l^1;
if(y==k)k=x;else (s[z][0]==y)?s[z][0]=x:s[z][1]=x;
F[x]=z;F[y]=x;F[s[x][r]]=y;
s[y][l]=s[x][r];s[x][r]=y;up(y);up(x);
}
void splay(int x,int &k){
while(x!=k){
int y=F[x],z=F[y];
if(y!=k){
(s[y][0]==x^s[z][0]==y)?rote(x,k):rote(y,k);
}
rote(x,k);
}
}
void make(int l,int r,int f){
if(l>r)return;int x=sit[l],be=sit[f];
if(l==r){
F[x]=be;size[x]=1;
(l<f)?s[be][0]=x:s[be][1]=x;return;
}
int Mid=(l+r)>>1;x=sit[Mid];
make(l,Mid-1,Mid);make(Mid+1,r,Mid);
F[x]=be;up(Mid); (Mid<f)?s[be][0]=x:s[be][1]=x;
}
int search(int k,int rank){
down(k);int l=s[k][0],r=s[k][1];
if(size[l]+1==rank)return k;
else if(size[l]>=rank)return search(l,rank);
else return search(r,rank-size[l]-1);
}
void rev(int l,int r){
int x=search(rt,l),y=search(rt,r+2);
splay(x,rt);splay(y,s[x][1]);
tip[s[y][0]]^=1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n+2;i++)sit[i]=++sz;
make(1,n+2,0);rt=(n+3)>>1;
for(int i=1;i<=m;i++){int l,r;scanf("%d%d",&l,&r);rev(l,r);}
for(int i=2;i<=n+1;i++)printf("%d ",search(rt,i)-1);puts("");
return 0;
}