BZOJ3226: [Sdoi2008]校门外的区间
感觉很有趣的题呢。
每个点拆成两个,线段树维护。
不过这题难点其实在输入输出。
#include<bits/stdc++.h> #define N (65535<<1) #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define K l,r,k #define L l,M,P #define R M+1,r,S #define Z \ int l=0,int r=N,int k=1 int u[1<<18],v[1<<18],a[N+10]; template<int d> void same(int k){ u[k]=d; v[k]=0; } void flip(int k){ (~u[k]?u[k]:v[k])^=1; } void (*operate[3])(int) ={same<0>,same<1>,flip}; void devolve(int k){ int d=v[k]?2:u[k]; if(~d){ operate[d](P); operate[d](S); v[k]=0; u[k]=-1; } } void A(int d,int s,int t,Z){ if(s==l&&t==r) operate[d](k); else{ devolve(k); if(t<=M) A(d,s,t,L); else if(s>M) A(d,s,t,R); else{ A(d,s,M,L); A(d,M+1,t,R); } } } void finish(Z){ if(~u[k]) for(int i=l;i<=r;++i) a[i]=u[k]; else{ devolve(k); finish(L); finish(R); } } bool empty(){ for(int i=0;i<=N;++i) if(a[i]) return 0; return 1; } int main(){ memset(u,-1,sizeof u); char d[2],b[16]; while(~scanf("%s%s",d,b)){ char u,v; int s,t; sscanf(b,"%c%d,%d%c",&u,&s,&t,&v); s=s*2+(u=='('); t=t*2-(v==')'); if(s>t) continue; switch(*d){ case'D': A(0,s,t); break; case'U': A(1,s,t); break; case'S': A(2,s,t); break; default: if(s) A(0,0,s-1); if(t!=N) A(0,t+1,N); if(*d=='C') A(2,s,t); } } finish(); if(empty()) puts("empty set"); else for(int i=0;i<=N;++i){ if((!i||!a[i-1])&&a[i]) printf("%c%d,",i&1?'(':'[',i>>1); if(a[i]&&!a[i+1]) printf("%d%c ",i+1>>1,i&1?')':']'); } }