poj 3225 Help with Intervals(线段树进阶,处理区间,拆点)

来源:互联网 发布:c语言求真值表 编辑:程序博客网 时间:2024/05/23 12:06

题意:
求区间的交,并,补,对称差。。
思路:
为了表示开闭区间,用偶数表示闭区间端点,奇数表示开区间的。
[2,3) -> 4, 5
(3, 7) -> 7, 13
集合操作可以分解为两种,set和xor。。
先实现这两种操作,再讨论情况。。

const int Maxn = 65550*2;#define lson(x) ((x)<<1)#define rson(x) (((x)<<1)|1)struct node {    int cover, x;};node a[Maxn*4+5];void xor_helper(int o) {    if (a[o].cover == -1) {        a[o].x ^= 1;    } else {        a[o].cover ^= 1;    }}// 两种标记不会同时存在void push_down(int o) {    int lc = lson(o), rc = rson(o);    if (a[o].cover != -1) {        a[lc].cover = a[rc].cover = a[o].cover;        a[lc].x = a[rc].x = 0;        a[o].cover = -1;    }    if (a[o].x) {        xor_helper(lc);xor_helper(rc);        a[o].x = 0;    }}void seg_update_cover(int L, int R, int o, int qL, int qR, int v) {    if (qL <= L && R <= qR) {        a[o].cover = v;        a[o].x = 0;        return;    }    push_down(o);    int lc = lson(o), rc = rson(o), mid = (L+R)>>1;    if (qL <= mid) seg_update_cover(L, mid, lc, qL, qR, v);    if (qR > mid) seg_update_cover(mid+1, R, rc, qL, qR, v);}void seg_update_xor(int L, int R, int o, int qL, int qR) {    if (qL <= L && R <= qR) {        xor_helper(o);return;    }    push_down(o);    int lc = lson(o), rc = rson(o), mid = (L+R)>>1;    if (qL <= mid) seg_update_xor(L, mid, lc, qL, qR);    if (qR > mid) seg_update_xor(mid+1, R, rc, qL, qR);}// query and markint mark[Maxn+5];void seg_query(int L, int R, int o) {   if (a[o].cover == 1) {rep(i, L-1, R-1) mark[i] = 1;return;}   if (!a[o].cover) return;   push_down(o);    int lc = lson(o), rc = rson(o), mid = (L+R)>>1;    seg_query(L, mid, lc);seg_query(mid+1, R, rc);}void seg_build(int L, int R, int o) {     a[o] = (node) {0, 0};     if (L < R) {         int lc = lson(o), rc = rson(o), mid = (L+R)>>1;         seg_build(L, mid, lc);seg_build(mid+1, R, rc);     }}// debugvoid seg_print(int L, int R, int o, int num) {    if (a[o].cover == 1) {printf("(%d %d)\n", L-1, R-1);return;}    if (a[o].cover == 0)return;    push_down(o);    int lc = lson(o), rc = rson(o), mid = (L+R)>>1;    seg_print(L, mid, lc, num+1);seg_print(mid+1, R, rc, num+1);}void ask() {    int n = Maxn;    memset(mark, 0, sizeof(mark));    seg_query(1, n, 1);    vector<pair<int, int> > ans;    int s = -1, e = -1;    for(int i=0;i<Maxn;++i) {        if (mark[i]) {            if (s == -1) s = i;            e = i;        } else {            if (s != -1) {                ans.push_back(make_pair(s, e));                s = -1;            }        }    }    if (ans.empty()) {printf("empty set\n");return;}    for (int i=0;i<ans.size();++i) {        int a = ans[i].first, b = ans[i].second;        char lhs = '[', rhs = ']';        if (ans[i].first & 1) {            lhs = '(';            --a;        }        if (ans[i].second & 1) {            rhs = ')';            ++b;        }        printf("%c%d,%d%c", lhs, a/2, b/2, rhs);        printf("%c", i == ans.size()-1 ? '\n':' ');    }}int main() {#ifndef ONLINE_JUDGE    freopen("input.in", "r", stdin);#endif // ONLINE_JUDGE    char a, b, c;int x, y;    int n = Maxn;    seg_build(1, n, 1);    while (scanf("%c %c%d,%d%c\n", &a, &b, &x, &y, &c) != EOF) {        x *= 2;y *= 2;        if (b == '(') ++x;if (c == ')') --y;        x += 1;y += 1; // 因为最小为0,所以对应到线段树上的区间时+1        //printf("%c %d %d\n", a, x-1, y-1);        if (x > y) continue;        if (a == 'U') {            seg_update_cover(1, n, 1, x, y, 1);        } else if (a == 'I') {            if (x - 1 >= 1)                seg_update_cover(1, n, 1, 1, x-1, 0);            seg_update_cover(1, n, 1, y+1, Maxn, 0);        } else if (a == 'D') {            seg_update_cover(1, n, 1, x, y, 0);        } else if (a == 'C') {            if (x - 1 >= 1)                seg_update_cover(1, n, 1, 1, x-1, 0);            seg_update_cover(1, n, 1, y+1, Maxn, 0);            seg_update_xor(1, n, 1, x, y);        } else if (a == 'S') {            seg_update_xor(1, n, 1, x, y);        }        //seg_print(1, n, 1, 0);        //ask();    }    ask();    return 0;}
0 0
原创粉丝点击