用-1表示’(‘,1表示’)‘,那么一个区间合法的充要条件就是最大前缀和最小后缀都为0
为了维护这两个值,还需要维护多三个:区间和,最小前缀,最大后缀。见(Merge函数)
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<sstream> #include<cmath> #include<climits> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #include<set> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define pb(a) push_back(a) #define INF 0x1f1f1f1f #define lson idx<<1,l,mid #define rson idx<<1|1,mid+1,r #define PI 3.1415926535898 template<class T> T min(const T& a,const T& b,const T& c) { return min(min(a,b),min(a,c)); } template<class T> T max(const T& a,const T& b,const T& c) { return max(max(a,b),max(a,c)); } #define clr0(a) memset(a,0,sizeof(a)) #define clr1(a) memset(a,-1,sizeof(a)) void debug() { #ifdef ONLINE_JUDGE #else freopen("d:\in.txt","r",stdin); // freopen("d:\out1.txt","w",stdout); #endif } int getch() { int ch; // while((ch=getchar())!=EOF) // { // if(ch!=' '&&ch!=' ')return ch; // } scanf(" %c",&ch); return ch; } // (->-1 )->1 struct node { //max_prefix min_prefix max_suffix min_suffix int maxp,minp,maxs,mins,sum; node(){} }; const int maxn=110000; node tree[maxn<<2]; int cha[maxn<<2]; int xorr[maxn<<2]; int Merge(node &q,node &a,node& b) { q.maxp=max(a.maxp,a.sum+b.maxp); q.minp=min(a.minp,a.sum+b.minp); q.maxs=max(b.maxs,b.sum+a.maxs); q.mins=min(b.mins,b.sum+a.mins); q.sum=a.sum+b.sum; return 0; } int PushUp(int idx) { Merge(tree[idx],tree[idx<<1],tree[idx<<1|1]); cha[idx]=0; xorr[idx]=1; return 0; } int PushDown(int idx,int l,int r) { int mid=(r+l)>>1; if(cha[idx]!=0) { //lson int lv=(mid-l+1)*cha[idx]; tree[idx<<1].sum=lv; tree[idx<<1].maxp=max(0,lv); tree[idx<<1].minp=min(0,lv); tree[idx<<1].maxs=max(0,lv); tree[idx<<1].mins=min(0,lv); //rson int rv=(r-mid)*cha[idx]; tree[idx<<1|1].sum=rv; tree[idx<<1|1].maxp=max(0,rv); tree[idx<<1|1].minp=min(0,rv); tree[idx<<1|1].maxs=max(0,rv); tree[idx<<1|1].mins=min(0,rv); //common cha[idx<<1]=cha[idx<<1|1]=cha[idx]; xorr[idx<<1]=xorr[idx<<1|1]=1; //father cha[idx]=0; } if(xorr[idx]<0) { //lson swap(tree[idx<<1].maxp,tree[idx<<1].minp); tree[idx<<1].maxp*=-1;tree[idx<<1].minp*=-1; swap(tree[idx<<1].maxs,tree[idx<<1].mins); tree[idx<<1].maxs*=-1;tree[idx<<1].mins*=-1; tree[idx<<1].sum*=-1; //rson swap(tree[idx<<1|1].maxp,tree[idx<<1|1].minp); tree[idx<<1|1].maxp*=-1;tree[idx<<1|1].minp*=-1; swap(tree[idx<<1|1].maxs,tree[idx<<1|1].mins); tree[idx<<1|1].maxs*=-1;tree[idx<<1|1].mins*=-1; tree[idx<<1|1].sum*=-1; // common xorr[idx<<1]*=-1;xorr[idx<<1|1]*=-1; xorr[idx]=1; } return 0; } int Build(int idx,int l,int r) { if(l==r) { char ch=getch(); int x=ch=='('?-1:1; tree[idx].sum=x; tree[idx].maxp=max(0,x); tree[idx].minp=min(0,x); tree[idx].maxs=max(0,x); tree[idx].mins=min(0,x); cha[idx]=0;xorr[idx]=1; return 0; } int mid=(r+l)>>1; Build(lson);Build(rson); PushUp(idx); return 0; } int Reverse(int idx,int l,int r,int tl,int tr) { if(tl<=l&&tr>=r) { xorr[idx]*=-1; tree[idx].sum*=-1; swap(tree[idx].maxp,tree[idx].minp); tree[idx].maxp*=-1;tree[idx].minp*=-1; swap(tree[idx].maxs,tree[idx].mins); tree[idx].maxs*=-1;tree[idx].mins*=-1; return 0; } PushDown(idx,l,r); int mid=(r+l)>>1; if(tl<=mid)Reverse(lson,tl,tr); if(tr>mid)Reverse(rson,tl,tr); PushUp(idx); return 0; } int Set(int idx,int l,int r,int tl,int tr,int v) { if(tl<=l&&tr>=r) { cha[idx]=v; xorr[idx]=1; v=v*(r-l+1); tree[idx].sum=v; tree[idx].maxp=max(0,v); tree[idx].minp=min(0,v); tree[idx].maxs=max(0,v); tree[idx].mins=min(0,v); return 0; } PushDown(idx,l,r); int mid=(r+l)>>1; if(tl<=mid)Set(lson,tl,tr,v); if(tr>mid)Set(rson,tl,tr,v); PushUp(idx); return 0; } node Query(int idx,int l,int r,int tl,int tr) { if(tl<=l&&tr>=r) { return tree[idx]; } PushDown(idx,l,r); int mid=(r+l)>>1; if(tl<=mid&&tr>mid) { node q,a,b; a=Query(lson,tl,tr); b=Query(rson,tl,tr); Merge(q,a,b); return q; }else if(tl<=mid) { return Query(lson,tl,tr); }else return Query(rson,tl,tr); } int main() { //debug(); int t; scanf("%d",&t); for(int ca=1;ca<=t;ca++) { int n; scanf("%d",&n); Build(1,1,n); int Q; scanf("%d",&Q); printf("Case %d: ",ca); for(int q=1;q<=Q;q++) { char op[100]; int l,r; scanf("%s%d%d",op,&l,&r); l++;r++; if(l>r)swap(l,r); switch(op[0]) { case 'q': { node x; x=Query(1,1,n,l,r); printf("%s ",x.maxp<=0&&x.mins>=0?"YES":"NO"); break; } case 's': { char v; v=getch(); Set(1,1,n,l,r,v=='('?-1:1); break; } case 'r': Reverse(1,1,n,l,r); break; default:break; } } printf(" "); } return 0; }
这道题有一点很奇怪,下面这个getch函数我用了几个月都没事,但是这题因为这个RE了两天
int getch() { int ch; while((ch=getchar())!=EOF) { if(ch!=' '&&ch!=' ')return ch; } return ch; }
如果不用这个,改成scanf()就过了。。。诡异