您的位置:首页 > 其它

BZOJ3226: [Sdoi2008]校门外的区间

2016-05-15 20:48 218 查看

感觉很有趣的题呢。

每个点拆成两个,线段树维护。

不过这题难点其实在输入输出。

#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?')':']');
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: