题意:给一个0-65535的区间,区间端点为L,R 区间有开区间闭区间之分,一开始你拥有一个S区间,为全空的区间
n次操作,每次操作有4种,
U: 把T区间L,R覆盖成1 (S U T)
I:把求给出T区间,求S和T交集,也就是把[-∞,l)(r,∞]覆盖成0
D:用原区间S减去所给区间T,也就是把 区间T置为零
C:用所给区间T减去S,然后把结果赋值给S,也就是把把[-∞,l)(r,∞]覆盖成0,把【l,r】取反
S:求异或,直接把区间【l,r】取反
上面的操作都可以用线段树的区间更新完成,分别是一个set操作,和一个求异或的操作,我们下放延迟标记的时候,注意分清先后,先下放set操作,并且set操作之后需要清空异或标记。
对于异或操作,如果当前节点有set标记,那么只需要把set标记取反即可,如果没有set标记则取反异或标记
还有一个很关键的问题是开闭区间的问题,我们用倍增区间法来解决此问题
(l, r) --> [2 * l + 1, 2 * r - 1]
(l, r] --> [2 * l + 1, 2 * r]
[l, r) --> [2 * l, 2 * r - 1]
[l, r] --> [2 * l, 2 *r]
我们用偶数点代表整数点,奇数点代表两个整数点之间的 所有非整数点,那么问题便解决了.
直接把端点乘2,左开则l++,右开则r--, 处理完后 最后输出 的端点为 l/2 (r+1)/2 如果l或r为奇数,对应开区间,反之闭区间
<span style="font-size:14px;">#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
#define ptf(ar1,ar2) printf("%d:%d\n",ar1,ar2);
typedef __int64 ll;
const ll maxn = 131570+500;
int vis[131570+500];
struct tree
{
int set[maxn*4],yihuo[maxn*4];
void pd_set(int i,int l,int r)
{
if (set[i]!=-1)
{
set[i<<1]=set[i<<1|1]=set[i];
yihuo[i<<1]=yihuo[i<<1|1]=yihuo[i]=0;
set[i]=-1;
}
if (yihuo[i])
{
if (set[i<<1]!=-1) set[i<<1]^=1;
else yihuo[i<<1]^=1;
if (set[i<<1|1]!=-1) set[i<<1|1]^=1;
else yihuo[i<<1|1]^=1;
yihuo[i]=0;
}
}
void update(int l,int r,int ql,int qr,int i,int val,int op)
{
if (ql>r||qr<l) return ;
if (ql<=l&&qr>=r)
{
if (op)
{
if (set[i]!=-1) set[i]^=1;
else yihuo[i]^=1;
}
else
{
set[i]=val;
yihuo[i]=0;
}
return ;
}
pd_set(i,l,r);
int m=(l+r)>>1;
update(l,m,ql,qr,i<<1,val,op);
update(m+1,r,ql,qr,i<<1|1,val,op);
}
void init()
{
// memset(sum,0,sizeof(sum));
// memset(yihuo,0,sizeof(yihuo));
// memset(set,-1,sizeof(set));
}
int query2( int l,int r,int i)
{
if (l==r)
{
if (set[i]==1) vis[r]=1;
return 0;
}
pd_set(i,l,r);
int mid=(l+r)>>1;
query2(l,mid,i<<1);
query2(mid+1,r,i<<1|1);
}
};
tree tp ;
int main( )
{
char op;
int l,r;
char lrat,rrat;
tp.init();
while(scanf("%c %c%d,%d%c",&op,&lrat,&l,&r,&rrat)!=EOF)
{
getchar();
l*=2;
r*=2;
if (lrat=='(') l++;
if (rrat==')') r--;
if (op=='U')
tp.update(0,131570,l,r,1,1,0);
if (op=='I')
{
tp.update(0,131570,0,l-1,1,0,0);
tp.update(0,131570,r+1,131570,1,0,0);
}
if (op=='D')
tp.update(0,131570,l,r,1,0,0);
if (op=='C')
{
tp.update(0,131570,0,l-1,1,0,0);
tp.update(0,131570,r+1,131570,1,0,0);
tp.update(0,131570,l,r,1,1,1);
}
if (op=='S')
tp.update(0,131570,l,r,1,1,1);
}
int i;
tp.query2(0,131570 ,1);
int line=0;
int exist=0;
for( i=0; i<=131570 ; i++)
{
if (vis[i])
{
exist=1;
if (line) printf(" ");
int j=i+1;
while(vis[j]&&j<=131570) j++;
j--;
if (i%2) printf("(");
else printf("[");
printf("%d,%d",i/2,(j+1)/2);
if (j%2)
printf(")");
else
printf("]");
line=1;
i=j;
}
}
if (exist==0)
printf("empty set");
printf("\n");
return 0;
}
</span>