bzoj2329 [HNOI2011]括号修复

网友投稿 535 2022-08-29

bzoj2329 [HNOI2011]括号修复

bzoj2329 [HNOI2011]括号修复

​​‎ 题目描述

一个合法的括号序列是这样定义的:

空串是合法的。如果字符串 S 是合法的,则(S)也是合法的。如果字符串 A 和 B 是合法的,则 AB 也是合法的。

现在给你一个长度为 N 的由‘(‘和‘)’组成的字符串,位置标号从 1 到 N。对这个字符串有下列四种操作:

Replace a b c:将[a,b]之间的所有括号改成 c。例如:假设原来的字符串为:))())())(,那么执行操作 Replace 2 7 ( 后原来的字符串变为:)(((((()(。Swap a b:将[a,b]之间的字符串翻转。例如:假设原来的字符串为:))())())(,那么执行操作 Swap 3 5 后原来的字符串变为:))))(())(。Invert a b:将[a,b]之间的‘(’变成‘)’,‘)’变成‘(’。例如:假设原来的字符串为:))())())(,那么执行操作 Invert 4 8 后原来的字符串变为:))((()(((。Query a b:询问[a,b]之间的字符串至少要改变多少位才能变成合法的括号序列。改变某位是指将该位的‘(’变成‘)’或‘)’变成‘(’。注意执行操作 Query 并不改变当前的括号序列。例如:假设原来的字符串为:))())())(,那么执行操作 Query 3 6

的结果为 2,因为要将位置 5 的‘)’变成‘(’并将位置 6 的‘(’变成‘)’。 输入输出格式

输入格式:

从文件input.txt中读入数据,输入文件的第一行是用空格隔开的两个正整数N和M,分别表示字符串的长度和将执行的操作个数。第二行是长度为N的初始字符串S。接下来的M行是将依次执行的M个操作,其中操作名与操作数之间以及相邻操作数之间均用空格隔开。30%的数据满足

N,M≤3000。100%的数据满足N,M≤100000。

输出格式:

输出文件 output.txt 包含 T 行,其中 T 是输入的将执行的 M 个操作中 Query 操作出现的次数。Query 操作的每次出现依次对应输出文件中的一行,该行只有一个非负整数,表示执行对应 Query 操作的结果,即:所指字符串至少要改变多少位才能变成合法的括号序列。输入数据

保证问题有解。 输入输出样例

输入样例#1: 复制

4 5 (((( Replace 1 2 ) Query 1 2 Swap 2 3 Invert 3 4 Query 1 4

输出样例#1: 复制

1 2

说明

样例解释:输入中有2个Query操作,所以输出有2行。执行第一个Query操作时的括号序列为))((,因改变第1位可使[1,2]之间的字符串变成合法的括号序列,故输出的第一行为1。执行第二个Query操作时的括号序列为)((),因要改变第1位和第2位才能使[1,4]之间的字符串变成合法的括号序列,故输出的第二行为2。

细节太多 蒟蒻我觉得讨论起来非常麻烦 不好想清楚 并且标记众多 需注意下放的时候的先后顺序(被坑死

首先括号序列:做过之前zjoi捉迷藏那道题 可以清楚的知道 我现在怎样维护括号序列了 那么就是维护一个a,b 那么这个a表示”)”这个括号的数量 b表示“(”这个括号的数量 那么我就可以知道 我需要输出的那个值就是(a+1)/2+(b+1)/2 这样的话就像线段树上 区间合并一样 左端点的b会和右端点的a消去 但是一开始我就是这么写 显然有问题 问题在哪里 因为尝试出例子画一画之后发现 我反转的时候因为信息不齐是错的 反转就是针对自己取反的那个操作 因为取反之后我的信息就改变了 比如对自己本身取反 可能直接都消没了 所以我需要维护两个值 1、现在序列的括号匹配值 2、 取反之后序列的括号匹配值 注意 在进行翻转的时候要针对我序列本身也要做一些取反的操作这时候我曾经的a,b现在变成了可以消去的部分 曾经可以消去的部分 现在变成了不可消去的部分 注意算一算他们的关系分类讨论下即可

注意下放的顺序 那个覆盖标记需要在最后下放 为什么 因为我一旦覆盖的话 我就会把其他两个标记清除那么如果我还存在其他的两个标记说明一定是覆盖之后造成的 如果我先下放覆盖再下放反转什么的操作 就会因为我主程序里先写的覆盖后写的反转等导致反转两次 没有反转很坑

#include#include#define N 110000using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar(); return x*f; }//sw对应invert操作int a[N],b[N],rev[N],sw[N],fa[N],c[N][2],v[N],l1[N],l2[N],r1[N],r2[N],size[N],tag[N],root,n,m; char op[10],s[N];// l1左边正常值l2左边反转值 r1右边正常值 r2右边反转值 inline void update(int x){ int l=c[x][0],r=c[x][1]; size[x]=size[l]+size[r]+1; l1[x]=l1[l]+max(0,l1[r]-r1[l]+v[x]);r1[x]=r1[r]+max(0,r1[l]-l1[r]-v[x]); l2[x]=l2[l]+max(0,l2[r]-r2[l]-v[x]);r2[x]=r2[r]+max(0,r2[l]-l2[r]+v[x]);}inline void build(int f,int l,int r){ if (l>r) return;int mid=l+r>>1; c[f][mid>f]=mid;fa[mid]=f;v[mid]=s[mid]; build(mid,l,mid-1);build(mid,mid+1,r);update(mid);}inline void pushdown(int x){ int l=c[x][0],r=c[x][1]; if (sw[x]){ v[l]=-v[l];tag[l]=-tag[l];swap(l1[l],l2[l]);swap(r1[l],r2[l]);sw[l]^=1; v[r]=-v[r];tag[r]=-tag[r];swap(l1[r],l2[r]);swap(r1[r],r2[r]);sw[r]^=1; sw[x]=0; } if (rev[x]){ swap(c[l][0],c[l][1]);swap(l1[l],r2[l]);swap(l2[l],r1[l]);rev[l]^=1; swap(c[r][0],c[r][1]);swap(l1[r],r2[r]);swap(l2[r],r1[r]);rev[r]^=1; rev[x]=0; } if (tag[x]){ tag[l]=tag[r]=v[l]=v[r]=tag[x]; if (tag[x]==1){ l1[l]=r2[l]=size[l];l2[l]=r1[l]=0; l1[r]=r2[r]=size[r];l2[r]=r1[r]=0; }else{ l2[l]=r1[l]=size[l];l1[l]=r2[l]=0; l2[r]=r1[r]=size[r];l1[r]=r2[r]=0; }tag[x]=0; }}inline int find(int x,int sz){ pushdown(x);int l=c[x][0],r=c[x][1]; if (size[l]+1==sz) return x; if(sz<=size[l]) return find(l,sz);return find(r,sz-size[l]-1); }inline void rotate(int x,int &tar){ int y=fa[x],z=fa[y]; if (y==tar) tar=x;else c[z][c[z][1]==y]=x; int l=c[y][1]==x,r=l^1; fa[c[x][r]]=y;fa[y]=x;fa[x]=z; c[y][l]=c[x][r];c[x][r]=y;update(y);update(x);}inline void splay(int x,int &tar){ while(x!=tar){ int y=fa[x],z=fa[y]; if (y!=tar){ if (c[y][0]==x^c[z][0]==y) rotate(x,tar);else rotate(y,tar); }rotate(x,tar); }}inline int split(int x,int y){ int xx=find(root,x),yy=find(root,y); splay(yy,root);splay(xx,c[root][0]);return c[xx][1]; }inline void print(int x){ pushdown(x); if (c[x][0]) print(c[x][0]); printf("%d %d %d %d %d %d\n",size[x],v[x],l1[x],r1[x],l2[x],r2[x]); if (c[x][1]) print(c[x][1]);}int main(){ freopen("bzoj2329.in","r",stdin); n=read();m=read();scanf("%s",s+2); for (int i=2;i<=n+1;++i) s[i]=s[i]==')'?1:-1; build(0,1,n+2);root=n+3>>1; for (int i=1;i<=m;++i){ scanf("%s",op);int x=read(),y=read(),tmp=split(x,y+2); if (op[0]=='R'){ char ch[2];scanf("%s",ch);tag[tmp]=ch[0]==')'?1:-1;sw[tmp]=rev[tmp]=0; v[tmp]=tag[tmp];if (tag[tmp]==1) l1[tmp]=r2[tmp]=size[tmp],l2[tmp]=r1[tmp]=0; else r1[tmp]=l2[tmp]=size[tmp],r2[tmp]=l1[tmp]=0;update(fa[tmp]);update(root); } if (op[0]=='Q') printf("%d\n",((l1[tmp]+1)>>1)+(r1[tmp]+1>>1)); if (op[0]=='S'){rev[tmp]^=1;swap(c[tmp][0],c[tmp][1]);swap(l1[tmp],r2[tmp]);swap(l2[tmp],r1[tmp]);update(fa[tmp]);update(root);} if (op[0]=='I'){sw[tmp]^=1;v[tmp]=-v[tmp];tag[tmp]=-tag[tmp];swap(l1[tmp],l2[tmp]);swap(r1[tmp],r2[tmp]);update(fa[tmp]);update(root);} // print(root);puts(""); } return 0;}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:建议收藏备查!MySQL 常见错误代码说明
下一篇:hdu1712 ACboy needs your help
相关文章

 发表评论

暂时没有评论,来抢沙发吧~