链接
时间限制:4 s 内存限制:128 MB
【题目描述】
注意:以评测系统提供的输入输出文件名为准!
这个问题乍一看很棘手,因为他询问的东西很奇怪,所以我们考虑如果只有询问操作,我们应该怎么做,我们模拟一个栈来模拟括号匹配的过程,可以发现最终栈中剩下的元素一定是形如)))(((的,这时我们有一个结论 变成合法的最少修改次数为(p/2)+(q/2),注意该式子是要上取整,并且只对于p+q是偶数,奇数并不能实现完全匹配,p和q分别代表无法匹配的)和(的个数,那么问题就转换为了求出序列中无法匹配的)和(的个数,还是很难搞。
我们不妨对原序列做一个转换,我们将所有的)视为-1,将所有的(视为1,那么,p事实上就是这段区间的最小前缀的相反数,而q就是这段区间的最大后缀,因为两者之和是等于区间和的,所以我们只需要维护其中一个即可。假设我们选择维护最大后缀,因为有区间翻转操作,所以我们需要额外维护一个区间最大前缀。
对于区间*-1的情况,我们考虑如何更新最大前缀和最大后缀,最大前缀*-1之后变成了最小前缀,而最小前缀+最大后缀=区间和,所以我们可以以这种方式求出新的最大后缀。
1 #include<cstdio> 2 #define ls ch[x][0] 3 #define rs ch[x][1] 4 #define mid ((l+r)>>1) 5 #define max(a,b) a>b?a:b 6 using namespace std; 7 const int inf=1e5+5; 8 int n,m; 9 char s[inf]; 10 int rt; 11 int ch[inf][2],fa[inf],siz[inf]; 12 int v[inf],rev[inf],reset[inf],mul[inf],sum[inf],lmax[inf],rmax[inf]; 13 bool get(int x){ 14 return ch[fa[x]][1]==x; 15 } 16 void swap(int &x,int &y){ 17 int tem=x; 18 x=y; 19 y=tem; 20 } 21 void update(int x){ 22 sum[x]=sum[ls]+sum[rs]+v[x]; 23 siz[x]=siz[ls]+siz[rs]+1; 24 lmax[x]=max(lmax[ls],sum[ls]+lmax[rs]+v[x]); 25 rmax[x]=max(rmax[rs],sum[rs]+rmax[ls]+v[x]); 26 } 27 void tagdown(int x){ 28 if(reset[x]){ 29 v[x]=reset[x]; 30 sum[ls]=reset[x]*siz[ls]; 31 sum[rs]=reset[x]*siz[rs]; 32 if(reset[x]>0){ 33 lmax[ls]=rmax[ls]=siz[ls]; 34 lmax[rs]=rmax[rs]=siz[rs]; 35 } 36 else { 37 lmax[ls]=rmax[ls]=0; 38 lmax[rs]=rmax[rs]=0; 39 } 40 reset[ls]=reset[rs]=reset[x]; 41 rev[x]=0; 42 mul[x]=1; 43 reset[x]=0; 44 return ; 45 } 46 if(rev[x]){ 47 swap(ch[ls][0],ch[ls][1]); 48 swap(ch[rs][0],ch[rs][1]); 49 swap(lmax[ls],rmax[ls]); 50 swap(lmax[rs],rmax[rs]); 51 rev[ls]^=1;rev[rs]^=1; 52 rev[x]=0; 53 } 54 if(mul[x]!=1){ 55 v[x]*=-1; 56 sum[ls]*=-1; 57 sum[rs]*=-1; 58 int tem=lmax[ls]; 59 lmax[ls]=sum[ls]+rmax[ls]; 60 rmax[ls]=sum[ls]+tem; 61 tem=lmax[rs]; 62 lmax[rs]=sum[rs]+rmax[rs]; 63 rmax[rs]=sum[rs]+tem; 64 mul[ls]*=-1;mul[rs]*=-1; 65 reset[ls]*=-1;reset[rs]*=-1;//这里忘记写了 66 mul[x]=1; 67 } 68 } 69 void zig(int x){ 70 int old=fa[x],oldf=fa[old]; 71 tagdown(old); 72 tagdown(x); 73 bool p=get(x); 74 if(oldf)ch[oldf][get(old)]=x; 75 fa[x]=oldf; 76 fa[ch[old][p]=ch[x][p^1]]=old; 77 fa[ch[x][p^1]=old]=x; 78 update(old); 79 update(x); 80 } 81 void splay(int x,int aim=0){ 82 for(int f;(f=fa[x])!=aim;zig(x)) 83 if(fa[f]!=aim)zig(get(x)==get(f)?f:x); 84 if(!aim)rt=x; 85 } 86 int build(int l,int r){ 87 if(l>r)return 0; 88 if(!rt)rt=mid; 89 int Ls=build(l,mid-1); 90 int Rs=build(mid+1,r); 91 if(Ls)fa[ch[mid][0]=Ls]=mid; 92 if(Rs)fa[ch[mid][1]=Rs]=mid; 93 mul[mid]=1; 94 rev[mid]=0; 95 reset[mid]=0; 96 update(mid); 97 return mid; 98 } 99 int kth(int x,int ned){ 100 tagdown(x); 101 if(siz[ls]+1==ned)return x; 102 if(ned<siz[ls]+1)return kth(ls,ned); 103 else return kth(rs,ned-siz[ls]-1); 104 } 105 void out(int x){ 106 tagdown(x); 107 printf("%d %d %d\n",x,ls,rs); 108 if(ls)out(ls); 109 if(rs)out(rs); 110 } 111 int main() 112 { 113 freopen("brackets.in","r",stdin); 114 freopen("brackets.out","w",stdout); 115 // freopen("1.txt","r",stdin); 116 scanf("%d%d",&n,&m); 117 scanf("%s",s); 118 for(int i=2;i<=n+1;i++){ 119 if(s[i-2]==‘)‘)v[i]=-1; 120 else v[i]=1; 121 } 122 n+=2; 123 build(1,n); 124 for(int i=1;i<=m;i++){ 125 scanf("%s",s); 126 int a,b; 127 scanf("%d%d",&a,&b); 128 a++;b++; 129 a=kth(rt,a-1); 130 b=kth(rt,b+1); 131 splay(a); 132 splay(b,rt); 133 int o=ch[b][0]; 134 if(s[0]==‘R‘){ 135 char c; 136 getchar(); 137 c=getchar(); 138 if(c==‘)‘)reset[o]=-1; 139 else reset[o]=1; 140 sum[o]=reset[o]*siz[o]; 141 if(reset[o]>0)lmax[o]=rmax[o]=siz[o]; 142 else lmax[o]=rmax[o]=0; 143 } 144 if(s[0]==‘S‘){ 145 rev[o]^=1; 146 swap(ch[o][0],ch[o][1]); 147 swap(lmax[o],rmax[o]); 148 } 149 if(s[0]==‘I‘){ 150 // out(rt); 151 mul[o]*=-1;//printf("%d\n",reset[o]); 152 reset[o]*=-1;//这里的操作可以保证tagdown中reset存在的情况下其他操作无需执行 153 sum[o]*=-1; 154 int tem=lmax[o]; 155 lmax[o]=sum[o]+rmax[o];//这个数一定是非负的 156 rmax[o]=sum[o]+tem; 157 } 158 if(s[0]==‘Q‘){ 159 // printf("%d %d %d\n",lmax[o],rmax[o],sum[o]); 160 printf("%d\n",(rmax[o]-sum[o]+1)/2+(rmax[o]+1)/2);//上取整 161 } 162 } 163 return 0; 164 }