这题目完全就是一个标记下传思想,通过这道题目,自己也对这思想了解的更为透彻了,异或标记和覆盖标记,-1表示区间可能在子区间覆盖,0表示没有,1表示有,异或标记覆盖区间要下传,通过fxor下传。然后开区间,闭区间就是用乘以2,因为开区间要-1或则+1表示,奇数表示开,偶数表示闭,看了解题报告,还写了那么久
#include<cstdio>
int c[1600000],x[1600000];
int hash[140000];
const int N=140000;
void fxor(int i)//异或标记下传
{
if(c[i]!=-1)
{
c[i]^=1;
}
else
x[i]^=1;
}
void down(int i)
{
if(c[i]!=-1)
{
c[2*i+1]=c[2*i]=c[i];
c[i]=-1;
x[2*i+1]=x[2*i]=0;
}
if(x[i])
{
fxor(2*i);
fxor(2*i+1);
x[i]=0;
}
}
void ud(char t,int i,int l,int r,int L,int R)
{
if(l==L&&r==R)
{
if(t=='U')
{
c[i]=1;
x[i]=0;
}
if(t=='D')
{
c[i]=0;
x[i]=0;
}
else
if(t=='C'||t=='S')
fxor(i);
return;
}
down(i);
int mid=(L+R)>>1;
if(mid>=r)
{
ud(t,2*i,l,r,L,mid);
if(t=='I'||t=='C')
x[2*i+1]=c[2*i+1]=0;
}
else
if(mid<l)
{
ud(t,2*i+1,l,r,mid+1,R);
if(t=='I'||t=='C')
x[2*i]=c[2*i]=0;
}
else
{
ud(t,2*i,l,mid,L,mid);
ud(t,2*i+1,mid+1,r,mid+1,R);
}
}
void dfs(int i,int l,int r)
{
if(c[i]==0)
return;
if(c[i]==1)
{
for(int i=l;i<=r;i++)
hash[i]=1;
return;
}
if(l==r)
return;
down(i);
int m=(l+r)>>1;
dfs(2*i,l,m);
dfs(2*i+1,m+1,r);
return;
}
int main()
{
char t,le,re;
int a,b;
x[1]=0;
c[1]=0;
while ( ~scanf("%c %c%d,%d%c\n",&t , &le , &a , &b , &re) ) {//发现以前自己读入数据方式太土了.
a <<= 1 , b <<= 1;
if (le == '(') a ++;
if (re == ')') b --;
if (a > b) {
if (t == 'C' || t == 'I') {
c[1] = x[1] = 0;
}
} else ud(t ,1, a , b , 0 , N);
}
dfs(1,0,N);
int s=-1,flag=0,e;
for(int i=0;i<N;i++)
{
if(hash[i])
{
if(s==-1)s=i;
e=i;
}
else
{
if(s!=-1)
{
if(flag)
printf(" ");
printf("%c%d,%d%c",s&1?'(':'[' , s>>1 , (e+1)>>1 , e&1?')':']');
flag=1;
s=-1;
}
}
}
if (!flag) printf("empty set");
puts("");
return 0;
}
,搓死了。。