题目链接如下:
感谢大佬:
POJ 3225(线段树) - starry_sky - 博客园
一道线段树的题。
首先看看转化:
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数组,用来表示是否覆盖,0表示没有覆盖这个区间,1表示覆盖,-1表示现在没有操作,依旧是lazy标记。
除此之外,还要有一个xor数组,代表这个区间是否是翻转的。
那使用上我们如果要翻转一个区间,先给xor打上标记,0代表不反转,1代表反转,所以很多操作做需要用异或来完成。
那翻转一个区间要做的就是,把xor数组向下push_down,直到遇到了一个cover的lazy tag表示这个区间是否覆盖了。然后可以对cover进行异或就完成了翻转。
对开区间闭区间也做了处理,对所有数字都乘以2,如果是闭区间就把数字放到奇数的位置,这样在处理的时候就巨方便。
代码如下所示:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<cmath>
#include<climits>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int MAXN=65555*2;
bool interval[MAXN];
int cover[MAXN<<2],XOR[MAXN<<2];
void FXOR(int rt){
if (cover[rt]!=-1) cover[rt]^=1;
else XOR[rt]^=1;
};
void push_down(int rt){
if (cover[rt]!=-1){// 说明要覆盖区间 子树的XOR无效 直接赋0
cover[rt<<1]=cover[rt<<1|1]=cover[rt];
XOR[rt<<1]=XOR[rt<<1|1]=0;
cover[rt]=-1;
}
if (XOR[rt]){
FXOR(rt<<1);
FXOR(rt<<1|1);
XOR[rt]=0;
}
}
void update(char op,int a,int b,int l,int r,int rt){
if (a<=l && r<=b){
if (op=='U'){
cover[rt]=1;
XOR[rt]=0;
}else if (op=='D'){
cover[rt]=0;
XOR[rt]=0;
}else if (op=='C' || op=='S'){
FXOR(rt);
}
return;
}
push_down(rt);
int mid=(l+r)>>1;
if (a<=mid){
update(op,a,b,lson);
}else if (op=='I' || op=='C'){
XOR[rt<<1]=cover[rt<<1]=0;
}
if (b>mid){
update(op,a,b,rson);
}else if (op=='I' || op=='C'){
XOR[rt<<1|1]=cover[rt<<1|1]=0;
}
}
void query(int l,int r,int rt){
if (cover[rt]==1){
for (int i = l; i <= r; ++i) {
interval[i]=true;
}
return;
}else if (cover[rt]==0) return;
if (l==r) return;
push_down(rt);
int mid=(l+r)>>1;
query(lson);
query(rson);
}
int main(){
cover[1]=XOR[1]=0;
char op,l,r;
int a,b;
// int count=0;
while (~scanf("%c %c%d,%d%c\n",&op,&l,&a,&b,&r)){
// cout<<op<<" "<<l<<a<<","<<b<<r<<endl;
a<<=1,b<<=1;
if (l=='(') a++;
if (r==')') b--;
if (a>b){
if (op=='C'||op=='I'){
cover[1]=XOR[1]=0;
}
} else{
update(op,a,b,0,MAXN,1);
}
// if (count++>=5) break;
}
query(0,MAXN,1);
bool flag=false;
int s=-1,e;
for (int i = 0; i <= MAXN; ++i) {
if (interval[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=true;
s=-1;
}
}
}
if (!flag) printf("empty set");
return 0;
}