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

Sample Output

2
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 }
View Code

 

posted @ 2016-07-10 18:52  HTWX  阅读(157)  评论(0编辑  收藏  举报