http://poj.org/problem?id=3225
两大难点:
1. 区间的集合操作:
2. 区间端点的开、闭的区分方式:
区间的端点x都要两种状态,要么包含x,要么不含x
——可见,每个数其实都要两个值来存储区间的开闭状态,我可以联想到每一个坐标乘以2!
即,对于区间左端点L,
L*2代表:[L
L*2+1代表:(L
而对于区间右端点R,
R*2代表:R]
R*2-1代表:R)
我们画一下草稿,就可以看出,上述原则实际上是:
经过计算后的数字k(比如,左闭端点L,计算后为k=L*2; 左开端点L,计算后为k=L*2+1),如果是:
① 偶数,代表包含k/2
② 奇数,代表一个开区间:( k/2, (k+1)/2 )
#include <cstdio> #include <iostream> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = (65535 + 5) << 1; // 每一个点都有开、闭两种状态,故乘以2 int XOR[MAXN << 2]; int cover[MAXN << 2]; bool hash[MAXN]; void pushdown(int rt) { // cover 优先于 XOR if(cover[rt] != -1) { cover[left] = cover[right] = cover[rt]; XOR[left] = XOR[right] = 0; cover[rt] = -1; } if(XOR[rt]) { // 需判断cover没有被赋值的情况 if(cover[left] != -1) { cover[left] ^= 1; } else { XOR[left] ^= 1; } if(cover[right] != -1) { cover[right] ^= 1; } else { XOR[right] ^= 1; } XOR[rt] = 0; } } void update(char type, int ql, int qr, int rt, int l, int r) { if(ql <= l && r <= qr) { if(type == ‘U‘) { cover[rt] = 1; XOR[rt] = 0; } else if(type == ‘D‘){ cover[rt] = 0; XOR[rt] = 0; } else if(type == ‘C‘ || type == ‘S‘) { if(cover[rt] != -1) cover[rt] ^= 1; // 这里要细心,跟上面的pushdown类似 else XOR[rt] ^= 1; } return; } pushdown(rt); int m = (l + r) >> 1; if(ql <= m) update(type, ql, qr, left, l, m); else { if(type == ‘I‘ || type == ‘C‘) { cover[left] = 0; XOR[left] = 0; } } if(qr > m) update(type, ql, qr, right, m+1, r); else { if(type == ‘I‘ || type == ‘C‘) { cover[right] = 0; XOR[right] = 0; } } } void query(int ql, int qr, int rt, int l, int r) { if(cover[rt] != -1) { if(cover[rt] == 1) { for(int i=l; i<=r; i++) { hash[i] = 1; } } return; } if(l == r) return; pushdown(rt); int m = (l + r) >> 1; query(ql, qr, left, l, m); query(ql, qr, right, m+1, r); } int main () { cover[1] = XOR[1] = 0; int a,b; char type, l, r; while(scanf("%c %c%d,%d%c", &type, &l, &a, &b, &r)!=EOF) { a <<= 1; b <<= 1; if(l == ‘(‘) a++; if(r == ‘)‘) b--; if(a > b) { if(type == ‘C‘ || type == ‘I‘) { cover[1] = XOR[1] = 0; } } else { update(type, a, b, 1, 0, MAXN); // O(lgn) } getchar(); } query(0, MAXN, 1, 0, MAXN); // O(nlgn) int s = -1, e, first=1; for(int i=0; i<=MAXN; i++) { // O(n) if(hash[i] == 1) { if(s == -1) { s = i; } e = i; } else if(s != -1) { if(first) first = 0; else printf(" "); printf("%c%d,%d%c", s&1?‘(‘:‘[‘, s>>1, (e+1)>>1, e&1?‘)‘:‘]‘); s = -1; } } if(first) printf("empty set\n"); else printf("\n"); return 0; }
时间: 2024-11-05 20:29:12