U:把区间[l,r]覆盖成1
I:把[-∞,l)(r,∞]覆盖成0
D:把区间[l,r]覆盖成0
C:把[-∞,l)(r,∞]覆盖成0 , 且[l,r]区间0/1互换
S:[l,r]区间0/1互换
cover记录成段覆盖,xo记录互换
当一个节点得到覆盖标记时把异或标记清空
当一个节点得到异或标记的时候,先判断覆盖标记,如果是0或1,直接改变一下覆盖标记,不然的话改变异或标记
开区间闭区间只要数字乘以2就可以处理(偶数表示端点,奇数表示两端点间的区间)
例: [2,3]=4->6 (2,3)=5->5 [2,3)=4->5
最后用hash查找一下即可
注意边界判断
PS:翻译了半天才发现题目竟然可以选择中文.........
#include "stdio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"
#include "iostream"
#include "algorithm"
using namespace std;
struct comp
{
int num1,num2;
char l,r,op;
} sca[300010];
struct comp1
{
int l,r,cover,mid,xo,x;
} data[300010];
int first;
int hash[300010];
void Pushdown(int k)
{
if (data[k].l==data[k].r) return ;
if (data[k].cover!=-1)
{
data[k*2].cover=data[k*2+1].cover=data[k].cover;
data[k*2].xo=data[k*2+1].xo=0;
data[k*2].x=data[k*2+1].x=data[k].cover;
data[k].cover=-1;
return ;
}
if (data[k].xo%2!=0)
{
if (data[k*2].cover==1) data[k*2].cover=0; // 覆盖标记不为-1时,直接改变覆盖标记
else
if (data[k*2].cover==0) data[k*2].cover=1;
else data[k*2].xo++;
if (data[k*2+1].cover==0) data[k*2+1].cover=1;
else
if (data[k*2+1].cover==1) data[k*2+1].cover=0;
else data[k*2+1].xo++;
if (data[k*2].x==1)
data[k*2].x=0;
else
if (data[k*2].x==0)
data[k*2].x=1;
if (data[k*2+1].x==1)
data[k*2+1].x=0;
else
if (data[k*2+1].x==0)
data[k*2+1].x=1;
data[k].xo=0;
}
}
void build(int l,int r,int k)
{
data[k].l=l;
data[k].r=r;
data[k].mid=(l+r)/2;
data[k].cover=-1;
data[k].xo=0;
data[k].x=0;
if (l==r) return ;
build(l,data[k].mid,k*2);
build(data[k].mid+1,r,k*2+1);
}
void update_cover(int l,int r,int k,int op)
{
if (data[k].l==l && data[k].r==r)
{
data[k].cover=op;
data[k].x=op;
data[k].xo=0;
return ;
}
Pushdown(k);
if (r<=data[k].mid) update_cover(l,r,k*2,op);
else
if (l>data[k].mid) update_cover(l,r,k*2+1,op);
else
{
update_cover(l,data[k].mid,k*2,op);
update_cover(data[k].mid+1,r,k*2+1,op);
}
if (data[k*2].x==data[k*2+1].x && data[k*2].x!=-1) data[k].x=data[k*2].x; else data[k].x=-1;
}
void update_xor(int l,int r,int k)
{
if (data[k].l==l && data[k].r==r)
{
if (data[k].x==0) data[k].x=1;
else
if (data[k].x==1) data[k].x=0;
if (data[k].cover==0) data[k].cover=1 ; // 覆盖标记不为-1时,直接改变覆盖标记
else
if (data[k].cover==1) data[k].cover=0;
else data[k].xo++;
return ;
}
Pushdown(k);
if (r<=data[k].mid) update_xor(l,r,k*2);
else
if (l>data[k].mid) update_xor(l,r,k*2+1);
else
{
update_xor(l,data[k].mid,k*2);
update_xor(data[k].mid+1,r,k*2+1);
}
if (data[k*2].x==data[k*2+1].x && data[k*2].x!=-1) data[k].x=data[k*2].x; else data[k].x=-1;
}
void search(int k)
{
int i;
if (data[k].x==1)
{
first=0;
for (i=data[k].l;i<=data[k].r;i++)
hash[i]=1;
return ;
}
else
if (data[k].x==0) return ;
else
{
Pushdown(k);
search(k*2);
search(k*2+1);
}
}
int main()
{
int s,e,n,a,b,i,m;
char ch[10];
n=0;
m=0;
while (scanf("%s",ch)!=EOF)
{
getchar();
n++;
sca[n].op=ch[0];
scanf("%c%d,%d%c\n",&sca[n].l,&sca[n].num1,&sca[n].num2,&sca[n].r);
if (sca[n].num1>m) m=sca[n].num1;
if (sca[n].num2>m) m=sca[n].num2;
}
build(0,m*2,1);
for (i=1;i<=n;i++)
{
a=sca[i].num1*2;
b=sca[i].num2*2;
if (sca[i].l=='(') a++;
if (sca[i].r==')') b--;
if (sca[i].op=='U')
{
if (a<=b) update_cover(a,b,1,1);
}
if (sca[i].op=='I')
{
if (a<=b)
{
if (a!=0) update_cover(0,a-1,1,0);
if (b!=m*2) update_cover(b+1,m*2,1,0);
}
else update_cover(0,m*2,1,0);
}
if (sca[i].op=='D')
{
if (a<=b)
update_cover(a,b,1,0);
}
if (sca[i].op=='C')
{
if (a<=b)
{
update_xor(a,b,1);
if (a!=0) update_cover(0,a-1,1,0);
if (b!=m*2) update_cover(b+1,m*2,1,0);
}
else update_cover(0,m*2,1,0);
}
if (sca[i].op=='S')
{
if (a<=b) update_xor(a,b,1);
}
}
first=1;
memset(hash,0,sizeof(hash));
search(1);
if (first==1) printf("empty set");
else
{
s=-1;
for (i=0;i<=m*2;i++)
if (hash[i]==1)
{
if (s==-1) s=i;
e=i;
}
else
if (s!=-1)
{
if (first==1) printf(" ");else first=1;
if (s%2==0) printf("["); else printf("(");
printf("%d,",s/2);
if (e%2==0) printf("%d]",e/2); else printf("%d)",e/2+1);
s=-1;
}
if (s!=-1)
{
if (first==1) printf(" ");else first=1;
if (s%2==0) printf("["); else printf("(");
printf("%d,",s/2);
if (e%2==0) printf("%d]",e/2); else printf("%d)",e/2+1);
s=-1;
}
}
}
本文介绍了一种处理区间覆盖及区间内元素异或操作的数据结构实现方法,通过使用覆盖标记与异或标记来高效更新区间状态,并通过递归分解与懒惰传播策略实现了灵活的区间操作。

1034

被折叠的 条评论
为什么被折叠?



