splay是个很好的东西,与线段树相比,它能够实现诸如将区间翻转等操作,而复杂度也是平均logn的
splay的复杂度优秀在于它是一棵二叉树,而一个节点又代表了一个区间,那么寻找一个区间[l,r]并修改或是询问它,利用二叉树的性质,只需要将l-1旋转至根,r+1旋转至根的左儿子处,那么根的左儿子的右儿子就代表了要修改的区间了,而因为它是一棵"平衡"二叉树,所以复杂度还是有保证的。
splay例题:
裸题(写前面几道时自己手还挺生的,模板不是很好):
bzoj1503
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int N=100050;
struct node
{
int l,r,f,s,v,num;
}tree[N];
int n,m,l,cnt,root,del;
void pushup(int x)
{
tree[x].s=tree[tree[x].l].s+tree[tree[x].r].s+1;
}
void zig(int &x)
{
int fa=tree[x].f;
int grfa=tree[fa].f;
if(fa==tree[grfa].l)
tree[grfa].l=x;
else
tree[grfa].r=x;
tree[x].f=grfa;
tree[fa].l=tree[x].r;
tree[tree[x].r].f=fa;
tree[x].r=fa;
tree[fa].f=x;
pushup(fa);
pushup(x);
if(fa==root)
root=x;
}
void zag(int &x)
{
int fa=tree[x].f;
int grfa=tree[fa].f;
if(fa==tree[grfa].l)
tree[grfa].l=x;
else
tree[grfa].r=x;
tree[x].f=grfa;
tree[fa].r=tree[x].l;
tree[tree[x].l].f=fa;
tree[x].l=fa;
tree[fa].f=x;
pushup(fa);
pushup(x);
if(fa==root)
root=x;
}
void splay(int &x,int d)
{
while(tree[x].f!=d)
{
if(tree[tree[x].f].l==x)
zig(x);
else
zag(x);
}
}
void insert(int k)
{
if(!root)
{
root=++cnt;
tree[cnt].num=k;
tree[cnt].s=1;
return ;
}
int p=root,z;
while(p)
{
z=p;
++tree[p].s;
if(k<tree[p].num)
p=tree[p].l;
else
p=tree[p].r;
}
if(tree[z].num>k)
tree[z].l=++cnt;
else
tree[z].r=++cnt;
tree[cnt].num=k;
tree[cnt].s=1;
tree[cnt].f=z;
splay(cnt,0);
}
int find(int x,int k)
{
if(k<=tree[tree[x].r].s)
{
return find(tree[x].r,k);
}
if(k==tree[tree[x].r].s+1)
return tree[x].num;
return find(tree[x].l,k-tree[tree[x].r].s-1);
}
int dec(int &x,int f)
{
if(!x) return 0;
int k;
if(tree[x].num+del<m)
{
k=dec(tree[x].r,x)+tree[tree[x].l].s+1;
tree[tree[x].r].s=tree[x].s-k;
x=tree[x].r;
tree[x].f=f;
}
else
{
k=dec(tree[x].l,x);
tree[x].s-=k;
}
return k;
}
int main()
{
scanf("%d%d",&n,&m);
while(n--)
{
char c[1];
int k;
scanf("%s%d",&c,&k);
if(c[0]=='I'&&k>=m)
insert(k-del);
if(c[0]=='F')
printf("%d\n",k<=tree[root].s?find(root,k)+del:-1);
if(c[0]=='A')
del+=k;
if(c[0]=='S')
{
del-=k;
l+=dec(root,0);
}
}
printf("%d\n",l);
}
bzoj1251
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#define lson tree[x].l
#define rson tree[x].r
using namespace std;
const int inf=0x3f3f3f3f;
const int N=100050;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node
{
int l,r,f,s,rev,mx,num,tag;
}tree[N];
int n,m,l,cnt,root,del,id[N];
void pushup(int x)
{
tree[x].s=tree[lson].s+tree[rson].s+1;
tree[x].mx=max(tree[lson].mx,tree[rson].mx);
tree[x].mx=max(tree[x].mx,tree[x].num);
}
void pushdown(int x)
{
int l=tree[x].l,r=tree[x].r,t=tree[x].tag;
if(t)
{
tree[x].tag=0;
if(l)
{
tree[l].tag+=t;
tree[l].mx+=t;
tree[l].num+=t;
}
if(r)
{
tree[r].tag+=t;
tree[r].mx+=t;
tree[r].num+=t;
}
}
if(tree[x].rev)
{
tree[x].rev=0;
tree[l].rev^=1;
tree[r].rev^=1;
swap(tree[x].l,tree[x].r);
}
}
void zig(int &x)
{
int fa=tree[x].f;
int grfa=tree[fa].f;
if(fa==tree[grfa].l)
tree[grfa].l=x;
else
tree[grfa].r=x;
tree[x].f=grfa;
tree[fa].l=tree[x].r;
tree[tree[x].r].f=fa;
tree[x].r=fa;
tree[fa].f=x;
pushup(fa);
pushup(x);
if(fa==root)
root=x;
}
void zag(int &x)
{
int fa=tree[x].f;
int grfa=tree[fa].f;
if(fa==tree[grfa].l)
tree[grfa].l=x;
else
tree[grfa].r=x;
tree[x].f=grfa;
tree[fa].r=tree[x].l;
tree[tree[x].l].f=fa;
tree[x].l=fa;
tree[fa].f=x;
pushup(fa);
pushup(x);
if(fa==root)
root=x;
}
void splay(int &x,int d)
{
while(tree[x].f!=d)
{
//cout<<x<<" "<<tree[x].f<<" "<<d<<endl;
if(tree[tree[x].f].l==x)
zig(x);
else
zag(x);
}
}
int find(int x,int k)
{
if(tree[x].tag||tree[x].rev)
pushdown(x);
if(k<=tree[tree[x].l].s)
return find(tree[x].l,k);
if(k==tree[tree[x].l].s+1)
return x;
return find(tree[x].r,k-tree[tree[x].l].s-1);
}
inline void update(int l,int r,int v)
{
int x=find(root,l),y=find(root,r+2);
splay(x,0);
splay(y,x);
int z=tree[y].l;
tree[z].tag+=v;
tree[z].num+=v;
tree[z].mx+=v;
}
inline void rever(int l,int r)
{
int x=find(root,l);
int y=find(root,r+2);
splay(x,0);
splay(y,x);
int z=tree[y].l;
tree[z].rev^=1;
}
inline void query(int l,int r)
{
int x=find(root,l);
int y=find(root,r+2);
splay(x,0);
splay(y,x);
int z=tree[y].l;
printf("%d\n",tree[z].mx);
}
inline void build(int l,int r,int f)
{
if(l>r)
return ;
int now=id[l],last=id[f];
if(l==r)
{
tree[now].f=last;
tree[now].s=1;
if(l<f)
tree[last].l=now;
else
tree[last].r=now;
return ;
}
int mid=(l+r)/2;
now=id[mid];
build(l,mid-1,mid);
build(mid+1,r,mid);
tree[now].f=last;
pushup(now);
if(mid<f)
tree[last].l=now;
else
tree[last].r=now;
}
int sz=0;
int main()
{
tree[0].mx=-inf;
n=read();
m=read();
for(int i=1;i<=n+2;i++)
id[i]=i;
build(1,n+2,0);
root=(n+3)/2;
for(int i=1;i<=m;i++)
{
int f=read(),l,r,val;
switch(f)
{
case 1:l=read();r=read();val=read();update(l,r,val);break;
case 2:l=read();r=read();rever(l,r);break;
case 3:l=read();r=read();query(l,r);break;
}
}
return 0;
}
bzoj3223
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
using namespace std;
const int N=100050;
struct node
{
int l,r,rev,f,s;
}tree[N];
void pushup(int x)
{
tree[x].s=tree[tree[x].l].s+tree[tree[x].r].s+1;
}
int a,b,n,m,id[N],root;
void pushdown(int x)
{
if(tree[x].rev)
{
tree[x].rev=0;
tree[tree[x].l].rev^=1;
tree[tree[x].r].rev^=1;
swap(tree[x].l,tree[x].r);
}
}
void build(int l,int r,int f)
{
if(l>r)
return ;
int now=id[l],last=id[f];
if(l==r)
{
tree[now].f=last;
tree[now].s=1;
if(l<f)
tree[last].l=now;
else
tree[last].r=now;
return ;
}
int mid=(l+r)/2;
now=id[mid];
build(l,mid-1,mid);
build(mid+1,r,mid);
tree[now].f=last;
pushup(mid);
if(mid<f)
tree[last].l=now;
else
tree[last].r=now;
}
void zig(int &x)
{
int fa=tree[x].f;
int grfa=tree[fa].f;
if(tree[grfa].l==fa)
tree[grfa].l=x;
else
tree[grfa].r=x;
tree[x].f=grfa;
tree[fa].l=tree[x].r;
tree[tree[x].r].f=fa;
tree[x].r=fa;
tree[fa].f=x;
pushup(fa);
pushup(x);
if(fa==root)
root=x;
}
void zag(int &x)
{
int fa=tree[x].f;
int grfa=tree[fa].f;
if(tree[grfa].r==fa)
tree[grfa].r=x;
else
tree[grfa].l=x;
tree[x].f=grfa;
tree[fa].r=tree[x].l;
tree[tree[x].l].f=fa;
tree[x].l=fa;
tree[fa].f=x;
pushup(fa);
pushup(x);
if(fa==root)
root=x;
}
void splay(int &x,int d)
{
while(tree[x].f!=d)
{
if(x==tree[tree[x].f].l)
zig(x);
else
zag(x);
}
}
int find(int x,int k)
{
//cout<<x<<" "<<k<<endl;
if(tree[x].rev)
pushdown(x);
if(k<=tree[tree[x].l].s)
{
//cout<<tree[x].l<<" "<<k<<" "<<tree[tree[x].l].s<<endl;
return find(tree[x].l,k);
}
if(k==tree[tree[x].l].s+1)
return x;
return find(tree[x].r,k-tree[tree[x].l].s-1);
}
void rev(int l,int r)
{
int x=find(root,l);
int y=find(root,r+2);
//cout<<x<<" "<<y<<endl;
splay(x,0);
//cout<<tree[0].s<<"LLLLL"<<endl;
splay(y,x);
int now=tree[y].l;
tree[now].rev^=1;
//cout<<tree[0].s<<"LLLLL"<<endl;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n+2;i++)
{
id[i]=i;
}
root=(n+3)>>1;
build(1,n+2,0);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
rev(a,b);
}
for(int i=2;i<=n+1;i++)
{
printf("%d ",find(root,i)-1);
}
}
bzoj1588
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int N=50005;
struct node
{
int l,r,fa,v,s,num;
}tree[N];
int n,root,cnt;
void pushup(int rt)
{
tree[rt].s=tree[tree[rt].l].s+tree[tree[rt].r].s+1;
}
void zig(int &rt)
{
int fa=tree[rt].fa;
int grfa=tree[fa].fa;
if(fa==tree[grfa].l)
tree[grfa].l=rt;
else
tree[grfa].r=rt;
tree[rt].fa=grfa;
tree[fa].l=tree[rt].r;
tree[tree[rt].r].fa=fa;
tree[fa].fa=rt;
tree[rt].r=fa;
pushup(rt);
pushup(fa);
if(fa==root)
root=rt;
}
void zag(int &rt)
{
int fa=tree[rt].fa;
int grfa=tree[fa].fa;
if(tree[grfa].l==fa)
tree[grfa].l=rt;
else
tree[grfa].r=rt;
tree[rt].fa=grfa;
tree[fa].r=tree[rt].l;
tree[tree[rt].l].fa=fa;
tree[fa].fa=rt;
tree[rt].l=fa;
pushup(rt);
pushup(fa);
if(root==fa)
root=rt;
}
void splay(int &rt,int d)
{
while(tree[rt].fa!=d)
{
if(tree[tree[rt].fa].l==rt)
zig(rt);
else
zag(rt);
}
}
void insert(int rt)
{
if(!root)
{
root=++cnt;
tree[cnt].s=1;
tree[cnt].num=rt;
return ;
}
int z=root,p;
while(z)
{
p=z;
tree[z].s++;
if(rt>tree[z].num)
z=tree[z].r;
else
z=tree[z].l;
}
tree[++cnt].s=1;
tree[cnt].num=rt;
tree[cnt].fa=p;
if(rt>tree[p].num)
tree[p].r=cnt;
else
tree[p].l=cnt;
splay(cnt,0);
}
int ask1(int rt)
{
if(!tree[rt].r)
return tree[rt].num;
else
return ask1(tree[rt].r);
}
int ask2(int rt)
{
if(!tree[rt].l)
return tree[rt].num;
else
return ask2(tree[rt].l);
}
int ans=0;
int main()
{
scanf("%d",&n);
int a;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
insert(a);
//cout<<tree[root].l<<" l:"<<tree[tree[root].l].num<<endl;
//cout<<tree[root].r<<" r:"<<tree[tree[root].r].num<<endl;
if((!tree[root].l)&&(!tree[root].r))
ans+=a;
else
if(!tree[root].r)
ans+=(a-ask1(tree[root].l));
else
if(!tree[root].l)
ans+=(ask2(tree[root].r)-a);
else
ans+=min((a-ask1(tree[root].l)),(ask2(tree[root].r)-a));
//cout<<ans<<endl;
}
cout<<ans;
}
bzoj1500(rewrite)
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include<queue>
using namespace std;
const int N=1000050;
const int INF=1000000000;
int c[N][2],fa[N],cnt,id[N],a[N];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
queue<int> q;
int root;
struct node
{
int mx,lx,rx,v,size,sum;
bool tag,rev;
}tree[N];
void pushup(int rt)
{
int l=c[rt][0],r=c[rt][1];
tree[rt].mx=max(tree[l].mx,max(tree[r].mx,tree[l].rx+tree[r].lx+tree[rt].v));
tree[rt].lx=max(tree[l].lx,tree[l].sum+tree[rt].v+tree[r].lx);
tree[rt].rx=max(tree[r].rx,tree[r].sum+tree[rt].v+tree[l].rx);
tree[rt].size=tree[l].size+tree[r].size+1;
tree[rt].sum=tree[rt].v+tree[l].sum+tree[r].sum;
}
void revv(int rt)
{
swap(c[rt][0],c[rt][1]);
swap(tree[rt].lx,tree[rt].rx);
}
void pushdown(int rt)
{
int l=c[rt][0],r=c[rt][1];
if(tree[rt].tag)
{
tree[rt].tag=tree[rt].rev=0;
if(l) tree[l].tag=1,tree[l].v=tree[rt].v,tree[l].sum=tree[l].size*tree[l].v,tree[l].lx=tree[l].rx=max(0,tree[l].sum),tree[l].mx=max(tree[l].sum,tree[l].v);
if(r) tree[r].tag=1,tree[r].v=tree[rt].v,tree[r].sum=tree[r].size*tree[r].v,tree[r].lx=tree[r].rx=max(0,tree[r].sum),tree[r].mx=max(tree[r].sum,tree[r].v);
}
if(tree[rt].rev)
{
tree[rt].rev=0;
if(l) tree[l].rev^=1,revv(l);
if(r) tree[r].rev^=1,revv(r);
}
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
l=(c[y][1]==x),r=l^1;
if(y==k)
k=x;
else
c[z][c[z][1]==y]=x;
fa[c[x][r]]=y;
fa[y]=x;
fa[x]=z;
c[y][l]=c[x][r];
c[x][r]=y;
pushup(y);
pushup(x);
}
void splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if((c[y][0]==x)^(c[z][0]==y)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int rk,int rt)
{
pushdown(rt);
int l=c[rt][0],r=c[rt][1];
if(tree[l].size>=rk)
return find(rk,l);
if(rk==tree[l].size+1)
return rt;
return find(rk-tree[l].size-1,r);
}
void rec(int x)
{
if(!x)
return ;
int l=c[x][0],r=c[x][1];
rec(l),rec(r),q.push(x);
c[x][0]=c[x][1]=fa[x]=0;
tree[x].lx=tree[x].rx=tree[x].mx=tree[x].sum=fa[x]=tree[x].tag=tree[x].v=tree[x].size=tree[x].rev=0;
}
int split(int k,int tot)
{
int l1=find(k,root);
int l2=find(k+1+tot,root);
splay(l1,root),splay(l2,c[l1][1]);
return c[l2][0];
}
void query(int k,int tot)
{
int f=split(k,tot);
printf("%d\n",tree[f].sum);
}
void modify(int k,int tot,int val)
{
int x=split(k,tot);
int y=fa[x];
tree[x].tag=1;
tree[x].v=val;
tree[x].sum=val*tree[x].size;
if(val>=0) tree[x].lx=tree[x].rx=tree[x].mx=tree[x].sum;
else tree[x].lx=tree[x].rx=0,tree[x].mx=tree[x].v;
pushup(y);
pushup(fa[y]);
}
void rever(int k,int tot)
{
int x=split(k,tot),y=fa[x];
if(!tree[x].tag)
{
revv(x);
tree[x].rev^=1;
pushup(y),pushup(fa[y]);
}
}
void erase(int k,int tot)
{
int x=split(k,tot),y=fa[x];
rec(x),c[y][0]=0;
pushup(y),pushup(fa[y]);
}
void build(int l,int r,int f)
{
if(l>r)
return ;
int mid=(l+r)/2,now=id[mid],last=id[f];
if(l==r)
{
tree[now].sum=a[l];
tree[now].size=1;
tree[now].lx=tree[now].rx=max(a[l],0),tree[now].mx=a[l];
tree[now].tag=tree[now].rev=0;
}
else
build(l,mid-1,mid),build(mid+1,r,mid);
tree[now].v=a[mid];fa[now]=last;
pushup(now);
c[last][mid>=f]=now;
}
void ins(int k,int tot)
{
for(int i=1;i<=tot;i++)
a[i]=read();
for(int i=1;i<=tot;i++)
if(!q.empty()) id[i]=q.front(),q.pop();
else id[i]=++cnt;
build(1,tot,0);
int z=id[(1+tot)>>1];
int x=find(k+1,root),y=find(k+2,root);
splay(x,root);
splay(y,c[x][1]);
fa[z]=y,c[y][0]=z;
pushup(y);
pushup(x);
}
char s[20];
int a1,b1,c1,n,m;
int main()
{
scanf("%d%d",&n,&m);
a[1]=a[n+2]=tree[0].mx=-INF;
for(int i=1;i<=n;i++)
a[i+1]=read(),id[i]=i;
id[n+1]=n+1,id[n+2]=n+2;
root=(n+3)>>1,cnt=n+2;
build(1,n+2,0);
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='G')
a1=read(),b1=read(),query(a1,b1);
else if(s[0]=='I')
a1=read(),b1=read(),ins(a1,b1);
else if(s[0]=='D')
a1=read(),b1=read(),erase(a1,b1);
else if(s[0]=='M'&&s[2]=='X')
printf("%d\n",tree[root].mx);
else if(s[0]=='M')
a1=read(),b1=read(),c1=read(),modify(a1,b1,c1);
else if(s[0]=='R')
a1=read(),b1=read(),rever(a1,b1);
}
}
应用:
bzoj1208
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
const int N=80050;
long long ans;
int c[N][2],a[N],root,v[N],lx[N],rx[N],id[N],mx[N],sum[N],fa[N],cnt;
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
int l=(c[y][1]==x);
int r=l^1;
if(y==k)
k=x;
else
c[z][c[z][1]==y]=x;
fa[c[x][r]]=y;
fa[y]=x;
fa[x]=z;
c[y][l]=c[x][r];
c[x][r]=y;
}
void splay(int x,int &k)
{
int y,z;
while(x!=k)
{
y=fa[x],z=fa[y];
if(y!=k)
{
if((c[y][0]==x)^(c[z][0]==y))
rotate(x,k);
else
rotate(y,k);
}
rotate(x,k);
}
}
void ins(int &k,int x,int last)
{
if(k==0)
{
k=++cnt;
v[k]=x;
fa[k]=last;
splay(k,root);
return ;
}
if(x<v[k])
ins(c[k][0],x,k);
else
ins(c[k][1],x,k);
}
void del(int x)
{
splay(x,root);
// cout<<c[x][0]<<" "<<c[x][1]<<endl;
if(!(c[x][0]*c[x][1]))
root=c[x][0]+c[x][1];
else
{
int k=c[x][1];
while(c[k][0])
k=c[k][0];
c[k][0]=c[x][0];
fa[c[x][0]]=k;
root=c[x][1];
// cout<<"OK"<<endl;
}
// cout<<root<<"PPPPPP"<<endl;
fa[root]=0;
}
int t1,t2;
void find1(int x,int aim)
{
if(x==0)
return ;
if(v[x]<=aim)
t1=x,find1(c[x][1],aim);
else
find1(c[x][0],aim);
}
void find2(int x,int aim)
{
if(x==0)
return ;
if(v[x]>=aim)
t2=x,find2(c[x][0],aim);
else
find2(c[x][1],aim);
}
int n,t,b,kind;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&t,&b);
// cout<<"kind:"<<kind<<" root"<<root<<endl;
if(!root)
{
ins(root,b,0);
kind=t;
}
else
if(t==kind)
ins(root,b,0);
else
{
t1=t2=-1;
find1(root,b);
find2(root,b);
// cout<<"t1:"<<t1<<" t2:"<<t2<<endl;
if(t1==-1)
ans=(ans+v[t2]-b)%1000000,del(t2);
else if(t2==-1)
ans=(ans+b-v[t1])%1000000,del(t1);
else
if(t1>=0&&t2>=0&&v[t2]-b<b-v[t1])
{
ans=(ans+v[t2]-b)%1000000;
del(t2);
}
else
ans=(ans+b-v[t1])%1000000,del(t1);
}
// cout<<"LLLLL";
}
printf("%d\n",ans);
}
bzoj2329
神题
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int N=1000050;
int n,m;
char s[1000050];
int a[N],id[N],fa[N],root;
int c[N][2];
struct node
{
int lx,lm,rx,rm,sum,v,size;
int rev,tag1,tag2;
}tree[N];
void tong1(int rt,int vl)
{
tree[rt].v=vl,tree[rt].tag2=tree[rt].rev=0,tree[rt].tag1=vl;
tree[rt].sum=tree[rt].size*vl;
tree[rt].lx=tree[rt].rx=max(tree[rt].sum,0);
tree[rt].lm=tree[rt].rm=min(tree[rt].sum,0);
}
void tong2(int rt)
{
tree[rt].lm=-tree[rt].lm,tree[rt].lx=-tree[rt].lx;
tree[rt].rm=-tree[rt].rm,tree[rt].rx=-tree[rt].rx;
swap(tree[rt].lx,tree[rt].lm),swap(tree[rt].rm,tree[rt].rx);
tree[rt].sum=-tree[rt].sum,tree[rt].v=-tree[rt].v;
if(tree[rt].tag1)tree[rt].tag1=-tree[rt].tag1;
else tree[rt].tag2^=1;
}
void revv(int rt)
{
swap(tree[rt].lx,tree[rt].rx);
swap(tree[rt].rm,tree[rt].lm);
swap(c[rt][0],c[rt][1]);
tree[rt].rev^=1;
}
void pushdown(int rt)
{
int l=c[rt][0],r=c[rt][1];
if(tree[rt].tag2)
{
if(l) tong2(l);
if(r) tong2(r);
tree[rt].tag2^=1;
}
if(tree[rt].rev)
{
if(l) revv(l);
if(r) revv(r);
tree[rt].rev^=1;
}
if(tree[rt].tag1)
{
if(l) tong1(l,tree[rt].tag1);
if(r) tong1(r,tree[rt].tag1);
tree[rt].tag1=0;
}
}
void pushup(int rt)
{
int l=c[rt][0],r=c[rt][1];
tree[rt].lm=min(tree[l].lm,tree[l].sum+tree[r].lm+tree[rt].v);
tree[rt].rm=min(tree[r].rm,tree[r].sum+tree[l].rm+tree[rt].v);
tree[rt].lx=max(tree[l].lx,tree[l].sum+tree[r].lx+tree[rt].v);
tree[rt].rx=max(tree[r].rx,tree[r].sum+tree[l].rx+tree[rt].v);
tree[rt].size=tree[l].size+tree[r].size+1;
tree[rt].sum=tree[l].sum+tree[r].sum+tree[rt].v;
}
void build(int l,int r,int f)
{
if(l>r)
return;
int mid=(l+r)/2,rt=id[mid],last=id[f];
if(l==r)
{
tree[rt].size=1;
tree[rt].sum=a[l];
tree[rt].tag1=tree[rt].tag2=tree[rt].rev=0;
tree[rt].lx=tree[rt].rx=max(0,tree[rt].v);
tree[rt].lm=tree[rt].rm=min(0,tree[rt].v);
}
else build(l,mid-1,mid),build(mid+1,r,mid);
tree[rt].v=a[mid];
fa[rt]=last;
pushup(rt);
c[last][mid>=f]=rt;
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
int l=c[y][1]==x,r=l^1;
if(y==k)
k=x;
else
c[z][c[z][1]==y]=x;
fa[c[x][r]]=y;
fa[x]=z;
fa[y]=x;
c[y][l]=c[x][r];
c[x][r]=y;
pushup(y);
pushup(x);
}
void splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(c[z][0]==y^c[y][0]==x) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int rt,int rk)
{
pushdown(rt);
int l=c[rt][0],r=c[rt][1];
if(tree[l].size>=rk)
return find(l,rk);
if(tree[l].size+1==rk)
return rt;
return find(r,rk-tree[l].size-1);
}
int split(int l,int r)
{
int l1=find(root,l),r1=find(root,r+2);
// cout<<l1<<" "<<r1<<endl;
splay(l1,root),splay(r1,c[l1][1]);
return c[r1][0];
}
char fanzhuan(int x)
{
return x==1 ?'(':')';
}
void dfs(int x)
{
pushdown(x);
if(c[x][0]) dfs(c[x][0]);
cout<<fanzhuan(tree[x].v);
if(c[x][1]) dfs(c[x][1]);
}
void repl(int l,int r,int vl)
{
int x=split(l,r),y=fa[x];
// dfs(x);
// cout<<endl;
tong1(x,vl);
pushup(y);
pushup(fa[y]);
}
void rever(int l,int r)
{
int x=split(l,r),y=fa[x];
revv(x);
pushup(y),pushup(fa[y]);
// dfs(x);
// cout<<endl;
}
void fan(int l,int r)
{
int x=split(l,r),y=fa[x];
tong2(x);
pushup(y),pushup(fa[y]);
}
void query(int l,int r)
{
int x=split(l,r);
printf("%d\n",(-tree[x].lm+1)/2+(tree[x].rx+1)/2);
}
int a1,b1;
char c1;
int zhuan(char x)
{
return x=='(' ?1:-1;
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s);
for(int i=1;i<=n;i++)
a[i+1]= s[i-1]=='(' ?1:-1;
for(int i=1;i<=n+2;i++)
id[i]=i;
build(1,n+2,0);
root=(n+3)>>1;
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='R')
scanf("%d%d%c%c",&a1,&b1,&c1,&c1),repl(a1,b1,zhuan(c1));
else if(s[0]=='I')
scanf("%d%d",&a1,&b1),fan(a1,b1);
else if(s[0]=='S')
scanf("%d%d",&a1,&b1),rever(a1,b1);
else
scanf("%d%d",&a1,&b1),query(a1,b1);
}
}
特殊:
操作:将一个区间[l,r]内的数字旋转k次(每次旋转区间内每个元素向右移一位,最右一个移动到最左面去)
将区间[l,r]分为[l,r-k],[r-k+1,r],那么这个操作的实质就是将[l,r-k]插到[r-k+1,r]的右边去,实质则是一次del操作+一次ins操作
(from poj3580)