题目:
题解:
平衡树基本操作----区间翻转
在这个题中,点的排名就是点的值,可以少写一步
代码:
#include <cstdio>
#include <iostream>
using namespace std;
const int N=100005;
int ch[N][2],f[N],size[N],delta[N],root,sz,key[N],n;
int get(int x){return ch[f[x]][1]==x;}
void updata(int now){size[now]=size[ch[now][0]]+size[ch[now][1]]+1;}
void pushdown(int now)
{
if (delta[now])
{
swap(ch[now][0],ch[now][1]);
delta[ch[now][0]]^=1;
delta[ch[now][1]]^=1;
delta[now]=0;
}
}
void rotate(int x)
{
pushdown(f[x]);
pushdown(x);
int old=f[x],oldf=f[old],which=get(x);
f[x]=oldf; if (oldf) ch[oldf][ch[oldf][1]==old]=x;
ch[old][which]=ch[x][which^1]; f[ch[x][which^1]]=old;
ch[x][which^1]=old; f[old]=x;
updata(old); updata(x);
}
void splay(int x,int to)
{
for (;f[x]!=to;rotate(x))
if (f[f[x]]!=to) rotate(get(x)==get(f[x])?f[x]:x);
if (!to) root=x;
}
int build(int fa,int l,int r)
{
if (l>r) return 0;
int mid=(l+r)>>1;
int now=++sz;
key[now]=mid; f[now]=fa;
int lch=build(now,l,mid-1);
int rch=build(now,mid+1,r);
ch[now][0]=lch; ch[now][1]=rch;
updata(now);
return now;
}
int find(int x)//位置为x的编号
{
int now=root;
while (1)
{
pushdown(now);
if (x<=size[ch[now][0]]) now=ch[now][0];
else
{
x-=size[ch[now][0]]+1;
if (!x) return now;
now=ch[now][1];
}
}
}
void rev(int l,int r)
{
l--;r++;
if (l==0 && r>n){delta[root]^=1;return;}
if (l==0)
{
int x=find(r);
splay(x,0);
delta[ch[root][0]]^=1;
return;
}
if (r>n)
{
int x=find(l);
splay(x,0);
delta[ch[root][1]]^=1;
return;
}
int x=find(l),y=find(r);
splay(x,0); splay(y,x);
delta[ch[ch[root][1]][0]]^=1;
}
void print(int now)
{
pushdown(now);
if (ch[now][0]) print(ch[now][0]);
printf("%d ",key[now]);
if (ch[now][1]) print(ch[now][1]);
}
int main()
{
int m;scanf("%d%d",&n,&m);
root=build(0,1,n);
for (int i=1;i<=m;i++)
{
int x,y;scanf("%d%d",&x,&y);
rev(x,y);
}
print(root);
}