2209: [Jsoi2011]括号序列
Description
Input
输入数据的第一行包含两个整数N和Q,分别表示括号序列的长度,以及操作的个数。 第二行包含一个长度为N的括号序列。 接下来Q行,每行三个整数t、x和y,分别表示操作的类型、操作的开始位置和操作的结 束位置,输入数据保证x不小于y。其中t=0表示询问操作、t=1表示反转操作、t=2表示翻转操 作。
Output
对于每一个询问操作,输出一行,表示将括号序列的该子序列修改为配对,所需的最少改动 个数。
Sample Input
6 3
)(())(
0 1 6
0 1 4
0 3 4
)(())(
0 1 6
0 1 4
0 3 4
Sample Output
2
2
0
2
0
HINT
100%的数据满足N,Q不超过10^5
。
用splay维护,重点是如何维护询问,如果我们把()这样的去掉,那么序列就变成了)))(((((这样的,如果设(为1,)为-1,则区间的rmax,lmin即为所求。。
类似求最大连续子段和。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 150000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 int n,m,rt,c[maxn][2],fa[maxn],li[maxn],ri[maxn]; 30 int lx[maxn],rx[maxn],sum[maxn],s[maxn],v[maxn]; 31 int t1,t2; 32 bool cov[maxn],rev[maxn],inv[maxn]; 33 void pushup(int x){ 34 int l=c[x][0],r=c[x][1]; 35 s[x]=s[l]+s[r]+1; 36 sum[x]=sum[l]+sum[r]+v[x]; 37 lx[x]=max(lx[l],sum[l]+v[x]+max(0,max(lx[r],sum[r]))); 38 rx[x]=max(rx[r],sum[r]+v[x]+max(0,max(rx[l],sum[l]))); 39 li[x]=min(li[l],sum[l]+v[x]+min(0,min(li[r],sum[r]))); 40 ri[x]=min(ri[r],sum[r]+v[x]+min(0,min(ri[l],sum[l]))); 41 } 42 void rotate(int x,int &k){ 43 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 44 if(y!=k)c[z][c[z][1]==y]=x; 45 else k=x; 46 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 47 c[y][l]=c[x][r];c[x][r]=y; 48 pushup(y);pushup(x); 49 } 50 void splay(int x,int &k){ 51 while(x!=k){ 52 int y=fa[x],z=fa[y]; 53 if(y!=k){ 54 if(c[z][0]==y^c[y][0]==x) 55 rotate(x,k); 56 else rotate(y,k); 57 } 58 rotate(x,k); 59 } 60 } 61 void cover(int x,int y){ 62 cov[x]=1;v[x]=y;rev[x]=inv[x]=0; 63 sum[x]=s[x]*y; 64 lx[x]=rx[x]=y>0?sum[x]:0; 65 li[x]=li[x]=y>0?0:sum[x]; 66 } 67 void rever(int x){ 68 if(cov[x])return ; 69 rev[x]^=1; 70 swap(c[x][0],c[x][1]); 71 swap(lx[x],rx[x]); 72 swap(li[x],ri[x]); 73 } 74 void invert(int x){ 75 inv[x]^=1;v[x]=-v[x]; 76 swap(li[x],lx[x]);li[x]=-li[x];lx[x]=-lx[x]; 77 swap(ri[x],rx[x]);ri[x]=-ri[x];rx[x]=-rx[x]; 78 sum[x]=-sum[x]; 79 if(cov[x])inv[x]=0; 80 } 81 void pushdown(int x){ 82 if(cov[x]){cover(c[x][0],v[x]);cover(c[x][1],v[x]);cov[x]=0;} 83 if(rev[x]){rever(c[x][0]);rever(c[x][1]);rev[x]=0;} 84 if(inv[x]){invert(c[x][0]);invert(c[x][1]);inv[x]=0;} 85 } 86 int find(int x,int k){ 87 pushdown(x); 88 int l=c[x][0],r=c[x][1]; 89 if(s[l]+1==k)return x; 90 else if(s[l]>=k)return find(l,k); 91 else return find(r,k-s[l]-1); 92 } 93 void split(int x,int y){ 94 t1=find(rt,x);t2=find(rt,y); 95 splay(t1,rt);splay(t2,c[t1][1]); 96 } 97 void build(int l,int r,int f){ 98 if(l>r)return ; 99 int mid=(l+r)>>1; 100 fa[mid]=f;c[f][mid>f]=mid; 101 if(l==r){ 102 s[mid]=1;li[mid]=ri[mid]=v[mid]>0?0:v[mid]; 103 lx[mid]=rx[mid]=v[mid]>0?v[mid]:0; 104 sum[mid]=v[mid]; 105 return ; 106 } 107 build(l,mid-1,mid);build(mid+1,r,mid); 108 pushup(mid); 109 } 110 int main(){ 111 //freopen("input.txt","r",stdin); 112 //freopen("output.txt","w",stdout); 113 n=read();m=read(); 114 v[1]=v[n+2]=0; 115 for2(i,2,n+1){ 116 char ch=getchar(); 117 while(ch!='('&&ch!=')')ch=getchar(); 118 if(ch=='(')v[i]=1; 119 else v[i]=-1; 120 } 121 build(1,n+2,0);rt=(1+n+2)>>1; 122 while(m--){ 123 int ch=read(),x=read(),y=read(); 124 split(x,y+2);int z=c[t2][0]; 125 if(!ch)printf("%d\n",(-li[z]+1)/2+(rx[z]+1)/2); 126 else if(ch==1)invert(z);else rever(z); 127 pushup(t2);pushup(t1); 128 } 129 return 0; 130 }