POJ 3225

基本参考http://blog.csdn.net/metalseed/article/details/8039326

总的来说,敲完一遍理解会更加好一点,标记下传法。

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互换

利用异或值来决定是否要翻转,注意标记下传时,孩子结点的值是否要翻转是根据父结点决定的。由于最新的状态是在最上层完成的,所以后代结点翻转状态基本没有,除了当父结点覆盖状态为-1(此时区间内部分子区间值为1),需要结合父结点来决定当前的异或值。

#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <algorithm>
using namespace std;    

const int maxn = 131072;
bool hash[maxn+1];
int cover[maxn<<2];
int XOR[maxn<<2];

void PushXOR(int rt){
    if(cover[rt]!=-1) cover[rt]^=1;
    else XOR[rt]^=1;
}

void PushDown(int rt){
    if(cover[rt]!=-1){
        cover[rt<<1]=cover[rt<<1|1]=cover[rt];
        XOR[rt<<1]=XOR[rt<<1|1]=0;
        cover[rt]=-1;
    }
    if(XOR[rt]){
        PushXOR(rt<<1);
        PushXOR(rt<<1|1);
        XOR[rt]=0;
    }
}

void update(char op,int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        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‘){
            PushXOR(rt);
        }
        return ;
    }
    PushDown(rt);
    int m=(l+r)>>1;
    if(L<=m) update(op,L,R,l,m,rt<<1);
    else if(op==‘I‘||op==‘C‘){ cover[rt<<1]=XOR[rt<<1]=0; }
    if(m<R) update(op,L,R,m+1,r,rt<<1|1);
    else if(op==‘I‘||op==‘C‘){ cover[rt<<1|1]=XOR[rt<<1|1]=0; }
}

void query(int l,int r,int rt){
    if(cover[rt]!=-1){
        if(cover[rt]>0){
            for(int i=l;i<=r;i++)
            hash[i]=true;
        }
        return ;
    }
    if(l==r) return ;
    PushDown(rt);
    int m=(l+r)>>1;
    query(l,m,rt<<1);
    query(m+1,r,rt<<1|1);
}

int main(){
    cover[1] = XOR[1] = 0;
    char op , l , r;
    int a , b;
 //   int tt=0;
    while (scanf("%c %c%d,%d%c",&op , &l , &a , &b , &r)!=EOF) {
        getchar();
//        tt++;
        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(tt==5) break;
    }
    memset(hash,false,sizeof(hash));
    query(0,maxn,1);
    bool flag = false;
    int s = -1 , e;
    for (int i = 0 ; i <= maxn ; i ++) {
        if (hash[i]) {
            if (s == -1) s = i;
            e = i;
        } else {
            if (s != -1) {
                if (flag) printf(" ");
                flag = true;
                printf("%c%d,%d%c",s&1?‘(‘:‘[‘ , s>>1 , (e+1)>>1 , e&1?‘)‘:‘]‘);
                s = -1;
            }
        }
    }
    if (!flag) printf("empty set");
    puts("");
    return 0;
}

时间: 2024-11-08 13:56:01

POJ 3225的相关文章

poj 3225 Help with Intervals(线段树)

题目链接:poj 3225 Help with Intervals 题目大意:模拟集合操作,输出最终的集合. 解题思路:线段树. U l r:[l,r]区间置为1 I l r:[0,l),(r,maxn]置为0 D l r:[l,r]区间置为0 C l r:[0,l),(r,maxn]置为0,[l,r]区间取逆 S l r:[l,r]区间取逆. 然后基本水水的线段树,注意一下区间开和闭. #include <cstdio> #include <cstring> #include &

poj 3225 区间(区间的交并补操作)

http://poj.org/problem?id=3225 一道题又做了一天..这道题对我来说起初有N多难点. 1:区间的开闭如何解决.. 2:怎样把区间的交并补.对称差转化为对线段树的操作. 后来与实验室的同学讨论了后解决了前面两个问题. 对于区间的开闭,可以将区间放大一倍,偶数点表示端点,奇数点表示区间内线段,前开的话左端点加1,右开的话右端点减1.例如[1,3]可以表示成[2,6],(1,3)表示成(3,5). 对于区间的交并补问题,可以转化为区间覆盖问题,若T区间为[a,b]. U T

poj 3225 Help with Intervals

http://poj.org/problem?id=3225 题意:对集合进行交.并.差.异或四种操作,输出几步操作的之后的集合. U [a,b]  :可以将[a,b]全部置为1:  I [a,b] :可以将[a,b]之外的全部置为0:   S-[a,b] :将[a,b]全部置为0:  [a,b]-s  :将[a,b]之外的全部置为0,[a,b]取反.  I [a,b]  :将[a,b]取反. 然后用线段树维护区间. 1 #include <cstdio> 2 #include <cst

POJ - 3225 Help with Intervals (开闭区间)

Description LogLoader, Inc. is a company specialized in providing products for analyzing logs. While Ikki is working on graduation design, he is also engaged in an internship at LogLoader. Among his tasks, one is to write a module for manipulating ti

POJ 3225(线段树)

POJ 3225 题 意 : 区 间 操 作 , 交 , 并 , 补 等 思 路 : 我 们 一 个 一 个 操 作 来 分 析 :( 用 0 和 1 表 示 是 否 包 含 区 间 , - 1 表 示 该 区 间 内 既 有 包 含 又有 不 包 含 ) U : 把 区 间 [l,r ] 覆 盖 成 1 I: 把 [ - ∞ ,l) ( r, ∞ ] 覆 盖 成 0 D : 把 区 间 [l,r ] 覆 盖 成 0 C : 把 [ - ∞ ,l) ( r, ∞ ] 覆 盖 成 0 , 且 [l

POJ 3225 Help with Intervals(线段树)

POJ 3225 Help with Intervals 题目链接 集合数字有的为1,没有为0,那么几种操作对应就是置为0或置为1或者翻转,这个随便推推就可以了,然后开闭区间的处理方式就是把区间扩大成两倍,偶数存点,奇数存线段即可 代码: #include <cstdio> #include <cstring> #define lson(x) ((x<<1)+1) #define rson(x) ((x<<1)+2) const int N = 65536

POJ - 3225 - Help with Intervals 【区间的并、交、差、对称差】

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;

poj 3225 Help with Intervals(线段树,区间更新)

Help with Intervals Time Limit: 6000MS   Memory Limit: 131072K Total Submissions: 12474   Accepted: 3140 Case Time Limit: 2000MS Description LogLoader, Inc. is a company specialized in providing products for analyzing logs. While Ikki is working on g

poj - 3225 Roadblocks(次短路)

http://poj.org/problem?id=3255 bessie 有时会去拜访她的朋友,但是她不想走最快回家的那条路,而是想走一条比最短的路长的次短路. 城镇由R条双向路组成,有N个路口.标号为1到N,问1号路口到N号路口的次短路长度是多少?次短路是 比最短路长度长的次短的路径.同一条边可以经过多次. 到某个顶点v的次短路要么帅到其他顶点u的最短路在加上u-v的边,要么是到u的次短路再加上u-v的边, 因此所需要求的就是到所有顶点的最短路和次短路,因此,对于每个顶点,我们记录的不仅仅是

(中等) POJ 3225 Help with Intervals , 线段树+集合。

Description LogLoader, Inc. is a company specialized in providing products for analyzing logs. While Ikki is working on graduation design, he is also engaged in an internship at LogLoader. Among his tasks, one is to write a module for manipulating ti