debug很爽,表示细节错误一个有一个。
注意:1:在更新打标记时,要把原始数据和维护数据一起更新!!
2:在序列问题中,查找一个数只能用size找排名来找,因为,序列可能翻转!!
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;
const int N=100005;
int n,m,a[N];
char s[N];
int fa[N],ch[N][2],rev[N],fz[N],rt,mxl[N],mxr[N],mil[N],mir[N],sum[N],size[N];
void up(int i)
{
int l=ch[i][0],r=ch[i][1];
size[i]=size[l]+size[r]+1;
sum[i]=sum[l]+sum[r]+a[i];
mxl[i]=max(0,max(sum[l]+a[i]+mxl[r],mxl[l]));
mxr[i]=max(0,max(sum[r]+a[i]+mxr[l],mxr[r]));
mil[i]=min(0,min(sum[l]+a[i]+mil[r],mil[l]));
mir[i]=min(0,min(sum[r]+a[i]+mir[l],mir[r]));
}
int build(int fat,int l,int r)
{
if (l>r) return 0;
int mid=(l+r)>>1;
fa[mid]=fat;size[mid]=1;
ch[mid][0]=build(mid,l,mid-1);
ch[mid][1]=build(mid,mid+1,r);
up(mid);
return mid;
}
void down(int i)
{
int pos,l=ch[i][0],r=ch[i][1];
if (fz[i])
{
fz[i]^=1,fz[l]^=1,fz[r]^=1;
sum[l]=-sum[l],sum[r]=-sum[r];
for (int j=0;j<=1;j++)
{
pos=ch[i][j];
a[pos]=-a[pos];
swap(mxl[pos],mil[pos]);
mxl[pos]=-mxl[pos];
mil[pos]=-mil[pos];
swap(mxr[pos],mir[pos]);
mxr[pos]=-mxr[pos];
mir[pos]=-mir[pos];
}
}
if (rev[i])
{
rev[i]^=1,rev[l]^=1,rev[r]^=1;
swap(ch[i][0],ch[i][1]);
swap(mxl[l],mxr[l]);
swap(mil[l],mir[l]);
swap(mxl[r],mxr[r]);
swap(mil[r],mir[r]);
}
}
stack<int> ss;
void rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if (ch[y][0]==x) l=0;else l=1;r=l^1;
if (z) if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
up(y);
}
void splay(int x,int k)
{
int y,z;
while (fa[x]!=k)
{
y=fa[x];z=fa[y];
if (z!=k)
{
if ((ch[z][0]==y)^(ch[y][0]==x)) rotate(x);else rotate(y);
}
rotate(x);
}
if (k==0) rt=x;
up(x);
}
int find_kth(int u,int k)//必须用名次查找位置!!!
{
down(u);
if (size[ch[u][0]]+1==k) return u;
if (size[ch[u][0]]>=k) return find_kth(ch[u][0],k);
return find_kth(ch[u][1],k-size[ch[u][0]]-1);
}
int split(int x,int y)
{
int posx=find_kth(rt,x-1);splay(posx,0);
int posy=find_kth(rt,y+1);splay(posy,posx);
return ch[posy][0];
}
inline int read()
{
int ans;char ch;
while ((ch=getchar())<'0'||ch>'9');ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans;
}
int main()
{
n=read(),m=read();
scanf("%s",s+1);
for (int i=2;i<=n+1;i++) if (s[i-1]=='(') a[i]=1;else a[i]=-1;
a[1]=a[n+2]=0;
rt=build(0,1,n+2);
int t,x,y,pos;
for (int i=1;i<=m;i++)
{
t=read(),x=read(),y=read();
x++,y++;
pos=split(x,y);
switch(t)
{
case 0:
printf("%d\n",-(mil[pos]-1)/2+(mxr[pos]+1)/2);
break;
case 1:
fz[pos]^=1;
a[pos]=-a[pos];//注意把原始数据更新!!查了好长时间
sum[pos]=-sum[pos];
swap(mxl[pos],mil[pos]);
mxl[pos]=-mxl[pos];
mil[pos]=-mil[pos];
swap(mxr[pos],mir[pos]);
mxr[pos]=-mxr[pos];
mir[pos]=-mir[pos];
up(fa[pos]);up(rt);
break;
case 2:
rev[pos]^=1;
swap(mxl[pos],mxr[pos]);
swap(mil[pos],mir[pos]);
up(fa[pos]),up(rt);
break;
}
}
return 0;
}