UESTC 1546 Bracket Sequence 线段树成段更新

来源:互联网 发布:tensorflow 遗传算法 编辑:程序博客网 时间:2024/06/05 01:01

题意:给定一个括号序列,可以对它进行set,对把一定范围内的括号变成某一种括号,reverse把左右括号互换,query一定范围内的括号序列是否合法。

做法:一开始的想法,节点记录未匹配的左右括号数,然后进行操作,因为小看了reverse操作(本来以为简单的把左右括号的值改一下就好了,可是...),WA。

然后百度大神,重要发现了一个好算法。

造成一我错 的原因是无法准确找的无法配对的右括号。造成右括号无法配对的原因是,右括号没有足够的最括号,所以,大神把左括号设为1,右括号为-1,这样从左到右计算,节点中值的最小值,这个最小值为0就可能完全匹配,但不一定(只是解决了右括号问题),而且再也不怕reverse了

        #include<cstdio>   #include<cstring>   #define left l,m,x<<1   #define right m+1,r,x<<1|1   const int LMT=100003;   int cov[LMT<<2],ox[LMT<<2],sum[LMT<<2],mxsum[LMT<<2],misum[LMT<<2];   char sec[LMT];   inline int max(int a,int b)   {       return a>b?a:b;   }   inline int min(int a,int b)   {       return a<b?a:b;   }   void ope(int op,int l,int r,int x)   {       cov[x]=op;       mxsum[x]=op==1?r-l+1:0;       misum[x]=op==-1?-r+l-1:0;       sum[x]=(r-l+1)*op;       ox[x]=0;   }   void fox(int x)   {       if(cov[x])       {           cov[x]*=-1;           sum[x]*=-1;           ox[x]=0;       }       else      {           ox[x]^=1;           sum[x]*=-1;       }       int t=mxsum[x];       mxsum[x]=-misum[x];       misum[x]=-t;   }   void cut(int l,int r,int x)   {       int m=(l+r)>>1;       if(cov[x])       {           ope(cov[x],left);           ope(cov[x],right);           cov[x]=0;       }       if(ox[x])       {           fox(x<<1);fox(x<<1|1);           ox[x]=0;       }   }   void pushup(int x)   {       sum[x]=sum[x<<1]+sum[x<<1|1];       misum[x]=min(misum[x<<1],sum[x<<1]+misum[x<<1|1]);       mxsum[x]=max(mxsum[x<<1],mxsum[x<<1|1]+sum[x<<1]);       /*******      MAXsum其实只是为了在翻转的时候用翻转的时候,以前不相和的括号就会相合,      这里的maxsum[x<<1|1]+sum[x<<1]提前做了这一步。      ****/  }   void update(int op,int L,int R,int l,int r,int x)   {       if(L<=l&&r<=R)       {           if(op==-1)           {               ope(-1,l,r,x);               ox[x]=0;           }           if(op==1)           {               ope(1,l,r,x);               ox[x]=0;           }           if(op==2)fox(x);           return;       }       cut(l,r,x);       int m=(l+r)>>1;       if(L<=m)update(op,L,R,left);       if(R>m)update(op,L,R,right);       pushup(x);   }   void query(int &mi,int &all,int L,int R,int l,int r,int x)   {       if(L<=l&&r<=R)       {           mi=misum[x];           all=sum[x];           return;       }       cut(l,r,x);       int m=(l+r)>>1,mi1=0,mi2=0,al1=0,al2=0;       if(L<=m)query(mi1,al1,L,R,left);       if(R>m)query(mi2,al2,L,R,right);       all=al1+al2;       mi=min(mi1,al1+mi2);   }   void init()   {       memset(cov,0,sizeof(cov));       memset(ox,0,sizeof(ox));       memset(sum,0,sizeof(sum));       memset(misum,0,sizeof(misum));       memset(mxsum,0,sizeof(mxsum));   }   int main(void)   {       int i,n,T,m,l,r,all,mi,I=1;       char ord[10],op;       scanf("%d",&T);       while(T--)       {           init();           scanf("%d%s",&n,sec);           for(i=0;sec[i];i++)           {               if(sec[i]=='(')                   update(1,i,i,0,n-1,1);               else update(-1,i,i,0,n-1,1);           }           scanf("%d",&m);           printf("Case %d:\n",I++);           while(m--)           {               scanf("%s",ord);               if(!strcmp(ord,"query"))               {                   scanf("%d%d",&l,&r);                   mi=all=0;                   query(mi,all,l,r,0,n-1,1);                   if(mi==0&&all==0)puts("YES");                   else puts("NO");               }               if(!strcmp(ord,"set"))               {                   scanf("%d%d",&l,&r);                   op=getchar();                   while(op!='('&&op!=')')op=getchar();                   if(op=='(')update(1,l,r,0,n-1,1);                   else update(-1,l,r,0,n-1,1);               }               if(!strcmp(ord,"reverse"))               {                   scanf("%d%d",&l,&r);                   update(2,l,r,0,n-1,1);               }           }printf("\n");    }               return 0;   }