双倍经验题好评
画了一下午括号没想出来QAQ简直蠢哭了
把左括号看成1,右括号看成-1,答案就是(最小前缀和的绝对值+1)/2+(最大后缀和+1)/2
然后因为有三个操作所以还要顺便维护下最大前缀和&&最小后缀和
BTW HNOI的那道题暴力比我的splay跑得快QAQ
为什么我的splay感觉就是在地上爬啊
2209:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100000+5; int fa[N],ch[N][2],sz[N],lmx[N],rmx[N],lmi[N],rmi[N],v[N],sum[N],root; int inv[N],rev[N]; #define lc(x) ch[x][0] #define rc(x) ch[x][1] void pushup(int x){ sz[x]=sz[lc(x)]+sz[rc(x)]+1; sum[x]=sum[lc(x)]+sum[rc(x)]+v[x]; lmx[x]=max(lmx[lc(x)],sum[lc(x)]+lmx[rc(x)]+v[x]); rmx[x]=max(rmx[rc(x)],sum[rc(x)]+rmx[lc(x)]+v[x]); lmi[x]=min(lmi[lc(x)],sum[lc(x)]+lmi[rc(x)]+v[x]); rmi[x]=min(rmi[rc(x)],sum[rc(x)]+rmi[lc(x)]+v[x]); } void makeinv(int x){ inv[x]^=1; swap(lmx[x],lmi[x]);lmx[x]*=-1;lmi[x]*=-1; swap(rmx[x],rmi[x]);rmx[x]*=-1;rmi[x]*=-1; v[x]*=-1;sum[x]*=-1; } void makerev(int x){ rev[x]^=1; swap(lmx[x],rmx[x]);swap(lmi[x],rmi[x]); swap(lc(x),rc(x)); } void pushdown(int x){ if(inv[x]){ makeinv(lc(x));makeinv(rc(x)); inv[x]=0; } if(rev[x]){ makerev(lc(x));makerev(rc(x)); rev[x]=0; } } void rotate(int x,int &k){ int y=fa[x],z=fa[y],l=ch[y][1]==x,r=l^1; if(y==k)k=x; else ch[z][ch[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[ch[x][r]]=y; ch[y][l]=ch[x][r];ch[x][r]=y; pushup(y);pushup(x); } void splay(int x,int &k){ while(x!=k){ int y=fa[x],z=fa[y]; if(y!=k){ if(ch[z][0]==y^ch[y][0]==x)rotate(x,k); else rotate(y,k); } rotate(x,k); } } int kth(int x,int k){ pushdown(x); int r=sz[lc(x)]+1; if(k==r)return x; else if(k<r)return kth(lc(x),k); else return kth(rc(x),k-r); } int split(int a,int b){ int x=kth(root,a),y=kth(root,b+2); splay(x,root);splay(y,ch[x][1]); return ch[y][0]; } void invert(int a,int b){ int x=split(a,b); makeinv(x); } void rever(int a,int b){ int x=split(a,b); makerev(x); } int abs(int x){ return x>0?x:-x; } int query(int a,int b){ int x=split(a,b); return (abs(lmi[x])+1>>1)+(rmx[x]+1>>1); } int build(int l,int r){ if(l>r)return 0; if(l==r){ lmi[l]=rmi[l]=min(0,v[l]); lmx[l]=rmx[l]=max(0,v[l]); sz[l]=1;sum[l]=v[l]; return l; }else{ int mid=l+r>>1; lc(mid)=build(l,mid-1);rc(mid)=build(mid+1,r); fa[lc(mid)]=fa[rc(mid)]=mid; pushup(mid); return mid; } } char s[N]; int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int n,m;scanf("%d%d",&n,&m); scanf("%s",s+2); for(int i=1;i<=n+2;i++) if(s[i]=='(')v[i]=1; else if(s[i]==')')v[i]=-1; root=build(1,n+2); int opt,a,b; while(m--){ scanf("%d%d%d",&opt,&a,&b); if(opt==0)printf("%d\n",query(a,b)); else if(opt==1)invert(a,b); else rever(a,b); } return 0; }2329:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100000+5; int fa[N],ch[N][2],sz[N],lmx[N],rmx[N],lmi[N],rmi[N],v[N],sum[N],root; int inv[N],rev[N],set[N]; #define lc(x) ch[x][0] #define rc(x) ch[x][1] void pushup(int x){ sz[x]=sz[lc(x)]+sz[rc(x)]+1; sum[x]=sum[lc(x)]+sum[rc(x)]+v[x]; lmx[x]=max(lmx[lc(x)],sum[lc(x)]+lmx[rc(x)]+v[x]); rmx[x]=max(rmx[rc(x)],sum[rc(x)]+rmx[lc(x)]+v[x]); lmi[x]=min(lmi[lc(x)],sum[lc(x)]+lmi[rc(x)]+v[x]); rmi[x]=min(rmi[rc(x)],sum[rc(x)]+rmi[lc(x)]+v[x]); } void makeinv(int x){ inv[x]^=1; swap(lmx[x],lmi[x]);lmx[x]*=-1;lmi[x]*=-1; swap(rmx[x],rmi[x]);rmx[x]*=-1;rmi[x]*=-1; v[x]*=-1;sum[x]*=-1; } void makerev(int x){ rev[x]^=1; swap(lmx[x],rmx[x]);swap(lmi[x],rmi[x]); swap(lc(x),rc(x)); } void makeset(int x,int flag){ inv[x]=rev[x]=0; set[x]=flag; sum[x]=flag*sz[x]; lmx[x]=rmx[x]=max(0,sum[x]); lmi[x]=rmi[x]=min(0,sum[x]); v[x]=flag; } void pushdown(int x){ if(set[x]){ makeset(lc(x),set[x]);makeset(rc(x),set[x]); set[x]=0; } if(inv[x]){ makeinv(lc(x));makeinv(rc(x)); inv[x]=0; } if(rev[x]){ makerev(lc(x));makerev(rc(x)); rev[x]=0; } } void rotate(int x,int &k){ int y=fa[x],z=fa[y],l=ch[y][1]==x,r=l^1; if(y==k)k=x; else ch[z][ch[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[ch[x][r]]=y; ch[y][l]=ch[x][r];ch[x][r]=y; pushup(y);pushup(x); } void splay(int x,int &k){ while(x!=k){ int y=fa[x],z=fa[y]; if(y!=k){ if(ch[z][0]==y^ch[y][0]==x)rotate(x,k); else rotate(y,k); } rotate(x,k); } } int kth(int x,int k){ pushdown(x); int r=sz[lc(x)]+1; if(k==r)return x; else if(k<r)return kth(lc(x),k); else return kth(rc(x),k-r); } int split(int a,int b){ int x=kth(root,a),y=kth(root,b+2); splay(x,root);splay(y,ch[x][1]); return ch[y][0]; } void invert(int a,int b){ int x=split(a,b); makeinv(x); } void rever(int a,int b){ int x=split(a,b); makerev(x); } void replace(int a,int b,int c){ int x=split(a,b); makeset(x,c); } int abs(int x){ return x>0?x:-x; } int query(int a,int b){ int x=split(a,b); return (abs(lmi[x])+1>>1)+(rmx[x]+1>>1); } int build(int l,int r){ if(l>r)return 0; if(l==r){ lmi[l]=rmi[l]=min(0,v[l]); lmx[l]=rmx[l]=max(0,v[l]); sz[l]=1;sum[l]=v[l]; return l; }else{ int mid=l+r>>1; lc(mid)=build(l,mid-1);rc(mid)=build(mid+1,r); fa[lc(mid)]=fa[rc(mid)]=mid; pushup(mid); return mid; } } char s[N]; int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int n,m;scanf("%d%d",&n,&m); scanf("%s",s+2); for(int i=1;i<=n+2;i++) if(s[i]=='(')v[i]=1; else if(s[i]==')')v[i]=-1; root=build(1,n+2); char opt[10],c[5]; int a,b; while(m--){ scanf("%s%d%d",opt,&a,&b); if(opt[0]=='Q')printf("%d\n",query(a,b)); else if(opt[0]=='I')invert(a,b); else if(opt[0]=='S')rever(a,b); else{ scanf("%s",c); replace(a,b,c[0]=='('?1:-1); } } return 0; }