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。
题解Here!
貌似重题了吧。。。
删删改改就好辣!
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 100010 using namespace std; int n,m,size=0,root; int val[MAXN]; char ch[MAXN]; struct Splay{ int f,s,rev,inv,son[2]; int v,sum,maxl,minl,maxr,minr;//v: 1 -> ( -1 -> ) }a[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } inline int min(const int x,const int y){return x<y?x:y;} inline int max(const int x,const int y){return x>y?x:y;} inline void pushup(int rt){ if(!rt)return; a[rt].s=a[a[rt].son[0]].s+a[a[rt].son[1]].s+1; a[rt].sum=a[a[rt].son[0]].sum+a[a[rt].son[1]].sum+a[rt].v; a[rt].maxl=max(a[a[rt].son[0]].maxl,a[a[rt].son[0]].sum+a[rt].v+a[a[rt].son[1]].maxl); a[rt].minl=min(a[a[rt].son[0]].minl,a[a[rt].son[0]].sum+a[rt].v+a[a[rt].son[1]].minl); a[rt].maxr=max(a[a[rt].son[1]].maxr,a[a[rt].son[1]].sum+a[rt].v+a[a[rt].son[0]].maxr); a[rt].minr=min(a[a[rt].son[1]].minr,a[a[rt].son[1]].sum+a[rt].v+a[a[rt].son[0]].minr); } inline void pushdown_rev(int rt){ if(!rt)return; a[rt].rev^=1; swap(a[rt].son[0],a[rt].son[1]); swap(a[rt].maxl,a[rt].maxr);swap(a[rt].minl,a[rt].minr); } inline void pushdown_inv(int rt){ if(!rt)return; a[rt].inv^=1; a[rt].v=-a[rt].v;a[rt].sum=-a[rt].sum; a[rt].maxl=-a[rt].maxl;a[rt].minl=-a[rt].minl; a[rt].maxr=-a[rt].maxr;a[rt].minr=-a[rt].minr; swap(a[rt].maxl,a[rt].minl);swap(a[rt].maxr,a[rt].minr); } inline void pushdown(int rt){ if(!rt)return; if(a[rt].rev){ pushdown_rev(a[rt].son[0]); pushdown_rev(a[rt].son[1]); a[rt].rev=0; } if(a[rt].inv){ pushdown_inv(a[rt].son[0]); pushdown_inv(a[rt].son[1]); a[rt].inv=0; } } inline void turn(int rt,int k){ int x=a[rt].f,y=a[x].f; pushdown(x);pushdown(rt); a[x].son[k^1]=a[rt].son[k]; if(a[rt].son[k])a[a[rt].son[k]].f=x; a[rt].f=y; if(y)a[y].son[a[y].son[1]==x]=rt; a[x].f=rt; a[rt].son[k]=x; pushup(x);pushup(rt); } void splay(int rt,int ancestry){ while(a[rt].f!=ancestry){ int x=a[rt].f,y=a[x].f; if(y==ancestry)turn(rt,a[x].son[0]==rt); else{ int k=a[y].son[0]==x?1:0; if(a[x].son[k]==rt){turn(rt,k^1);turn(rt,k);} else{turn(x,k);turn(rt,k);} } } if(ancestry==0)root=rt; } inline int newnode(int x){ int rt=++size; a[rt].son[0]=a[rt].son[1]=a[rt].f=0; a[rt].rev=a[rt].inv=0; a[rt].s=1; a[rt].v=a[rt].sum=val[x]; return rt; } int buildtree(int l,int r){ if(l>r)return 0; int lson=0,rson=0,mid=l+r>>1; lson=buildtree(l,mid-1); int rt=newnode(mid); rson=buildtree(mid+1,r); a[rt].son[0]=lson; a[rt].son[1]=rson; if(lson)a[lson].f=rt; if(rson)a[rson].f=rt; pushup(rt); return rt; } int kth(int rt,int k){ while(1){ pushdown(rt); int y=a[rt].son[0]; if(k>a[y].s+1){ k-=a[y].s+1; rt=a[rt].son[1]; } else if(k<=a[y].s)rt=y; else return rt; } } inline void reverse(int l,int r){ int front=kth(root,l),next=kth(root,r+2),q; splay(front,0);splay(next,front); q=a[next].son[0]; pushdown_rev(q); pushup(next);pushup(front); } inline void invert(int l,int r){ int front=kth(root,l),next=kth(root,r+2),q; splay(front,0);splay(next,front); q=a[next].son[0]; pushdown_inv(q); pushup(next);pushup(front); } inline void query(int l,int r){ int front=kth(root,l),next=kth(root,r+2),q; splay(front,0);splay(next,front); q=a[next].son[0]; int ans=((a[q].maxr+1)>>1)-(a[q].minl-1)/2; printf("%d ",ans); } void work(){ char k[2]; int f,x,y; while(m--){ f=read();x=read();y=read(); if(f==0)query(x,y); else if(f==1)invert(x,y); else reverse(x,y); } } void init(){ n=read();m=read(); scanf("%s",ch+2); for(int i=2;i<=n+1;i++)val[i]=(ch[i]==')'?-1:1); val[1]=val[n+2]=0; root=buildtree(1,n+2); } int main(){ init(); work(); return 0; }