POJ3225
题目链接:
http://poj.org/problem?id=3225
一道线段树的区间操作题,关键点是开区间和闭区间的处理和区间取反操作。
关于区间的操作,可以将数组扩大到两倍,其中奇数位代表开区间,偶数位代表闭区间。
而区间取反操作可以另外开一个数组记录下当前区间的状态,如果当前区间里只包含有一种状态就可以直接取反,如果有两种状态就对当前的异或标记取反,表示该区间已进行过取反操作。
查询操作就直接一个结点一个结点的查询,输出所有区间。
ac代码如下:
# include<iostream>
# include<stdio.h>
# include<string.h>
using namespace std;
const int maxn = 2e5 + 5;
int tree[maxn << 2];
int xortag[maxn << 2];
bool vis[maxn << 2];
void upxor(int rt){
if(tree[rt] == -1)
xortag[rt] ^= 1;
else{
xortag[rt] = false;
tree[rt] ^= 1;
}
}
void pushup(int rt){
if(tree[rt << 1] == -1 || tree[rt << 1 | 1] == -1)
tree[rt] = -1;
else if(tree[rt << 1] == tree[rt << 1 | 1])
tree[rt] = tree[rt << 1];
else
tree[rt] = -1;
}
void pushdown(int rt){
if(tree[rt] != -1){
tree[rt << 1] = tree[rt << 1 | 1] = tree[rt];
xortag[rt << 1] = xortag[rt << 1 | 1] = false;
}
else if(xortag[rt]){
xortag[rt] = false;
upxor(rt << 1);
upxor(rt << 1 | 1);
}
}
void updata1(int l, int r, int rt, int L, int R, int x){
if(L > R)
return;
if(L <= l && R >= r){
tree[rt] = x;
xortag[rt] = 0;
return;
}
pushdown(rt);
int mid = (l + r) >> 1;
if(L <= mid)
updata1(l, mid, rt << 1, L, R, x);
if(R > mid)
updata1(mid + 1, r, rt << 1 | 1, L, R, x);
pushup(rt);
}
void updata2(int l, int r, int rt, int L, int R){
if(L > R)
return;
if(L <= l && R >= r){
upxor(rt);
return;
}
pushdown(rt);
int mid = (l + r) >> 1;
if(L <= mid)
updata2(l, mid, rt << 1, L, R);
if(R > mid)
updata2(mid + 1, r, rt << 1 | 1, L, R);
pushup(rt);
}
void query(int l, int r, int rt){
if(tree[rt] == 1){
for(int i = l; i <= r; i++)
vis[i] = true;
return;
}
else if(!tree[rt])
return;
int mid = (l + r) >> 1;
pushdown(rt);
query(l, mid, rt << 1);
query(mid + 1, r, rt << 1 | 1);
}
int main(){
int x, y;
int cnt = 0;
char ch, op1, op2;
memset(tree, 0, sizeof(tree));
memset(xortag, 0, sizeof(xortag));
memset(vis, false, sizeof(vis));
while(~scanf("%c %c%d,%d%c\n", &ch, &op1, &x, &y, &op2)){
cnt++;
int l = x << 1;
int r = y << 1;
if(l > r)
continue;
if(op1 == '(')
l++;
if(op2 == ')')
r--;
if(ch == 'U')
updata1(0, maxn, 1, l, r, 1);
else if(ch == 'I'){
updata1(0, maxn, 1, 0, l - 1, 0);
updata1(0, maxn, 1, r + 1, maxn, 0);
}
else if(ch == 'D')
updata1(0, maxn, 1, l, r, 0);
else if(ch == 'C'){
updata2(0, maxn, 1, l, r);
updata1(0, maxn, 1, 0, l - 1, 0);
updata1(0, maxn, 1, r + 1, maxn, 0);
}
else if(ch == 'S')
updata2(0, maxn, 1, l, r);
if(cnt == 5)
break;
}
bool tag = false;
bool flag = false;
query(0, maxn, 1);
for(int i = 0; i <= maxn; i++){
if(vis[i] && !tag){
if(flag)
printf(" ");
flag = true;
tag = true;
if(i % 2)
printf("(%d,", i / 2);
else
printf("[%d,", i / 2);
}
if(!vis[i] && tag){
tag = false;
int temp = i - 1;
if(temp % 2)
printf("%d)", i / 2);
else
printf("%d]", i / 2);
}
}
if(!flag)
printf("empty set");
printf("\n");
return 0;
}