• Help with Intervals POJ


                                            Help with Intervals POJ - 3225     

    这题真的是困扰了我好久!!!(最后还是看了胡浩dalao的博客才写出来,不过,有一点的改变)

    题意:刚开始,有一个空集S,现给出以下操作(T 表示一个集合)

    U    T    :S与T取并集。

    I      T    :S与T取交集。

    D    T    :S对T取补集。

    C    T    :T对S取补集。

    S    T    :S对T取补集,T对S取补集,然后这两者取并集。

    (对集合的交,并,补不太清楚的可以去看一下高中课本,或者百度以下,定义很简单的)

    思路:我们可以用点的覆盖来表示集合S,那么,对于各个操作,我们就可以定义为

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

    (可以自己手动模拟一下这几个操作)

    其中 0 1互换就是亦或操作。

    不过,还有一个难点就是,怎么表示开区间和闭区间呢?

    其实,只要把左右区间都乘上2偶数表示端点,奇数表示两端点间的区间)就可以解决这个问题了。最后只需判断区间的奇偶性,就可以判断是区间还是闭区间。

    那么,回到问题,由于有两种操作,所以我们需要准备两个lazy标记,一个cover表示覆盖,一个Xor表示取亦或

    还有一点需要注意的是,如果对于一个区间,我们覆盖掉他了,那么之前,对于这个区间的所有亦或操作都是无用的。所以,每覆盖掉一个区间,我们都需要将这个区间的亦或标记清空!

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    const int Max=131073;
    int cover[Max<<2],Xor[Max<<2],flag[Max];//两个lazy标记,flag记录最后的区间覆盖情况
    void PushDown(int rt){//将lazy标记传向下传递
        if(cover[rt]!=-1){
            cover[rt<<1]=cover[rt<<1|1]=cover[rt];
            Xor[rt<<1]=Xor[rt<<1|1]=0;//清空亦或标记
            cover[rt]=-1;
        }
        else if(Xor[rt]){//亦或操作,如果区间被覆盖,那么,直接对区间取亦或.区间没被覆盖,取亦或无效,所以对Xor标记亦或
            if(cover[rt<<1]!=-1) cover[rt<<1]^=1;
            else Xor[rt<<1]^=1;
            if(cover[rt<<1|1]!=-1) cover[rt<<1|1]^=1;
            else Xor[rt<<1|1]^=1;
            Xor[rt]=0;
        }
    }
    void update(int x,int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R){
            cover[rt]=x;
            Xor[rt]=0;
            return;
        }
        if(l==r) return;
        PushDown(rt);
        int m=(l+r)>>1;
        if(L<=m) update(x,L,R,lson);
        if(R>m) update(x,L,R,rson);
    }
    void FXOR(int L,int R,int l,int r,int rt){
        if(L<=l&&r<=R){//同理,区间被覆盖则直接亦或,否则,对自己亦或
            if(cover[rt]!=-1) cover[rt]^=1;
            else Xor[rt]^=1;
            return ;
        }
        if(l==r) return ;
        PushDown(rt);
        int m=(l+r)>>1;
        if(L<=m) FXOR(L,R,lson);
        if(R>m) FXOR(L,R,rson);
    }
    void query(int l,int r,int rt){
        if(cover[rt]==1){//flag记录区间覆盖情况
            for(int i=l;i<=r;i++)
                flag[i]=1;
            return ;
        }
        else if(cover[rt]==0) return;
        if(l==r) return;
        PushDown(rt);
        int m=(l+r)>>1;
        query(lson);
        query(rson);
    }
    int main(){
        char ch,a,b;
        int l,r;
        while(~scanf("%c %c%d,%d%c",&ch,&a,&l,&r,&b)){
            getchar();
            l<<=1,r<<=1;
            if(a=='(') l++;
            if(b==')') r--;
            if(ch=='U') update(1,l,r,0,Max,1);//分别对应思路里面提到的操作
            else if(ch=='I'){
                update(0,0,l-1,0,Max,1);
                update(0,r+1,Max,0,Max,1);
            }
            else if(ch=='D')
                update(0,l,r,0,Max,1);
            else if(ch=='C'){
                FXOR(l,r,0,Max,1);
                update(0,0,l-1,0,Max,1);
                update(0,r+1,Max,0,Max,1);
            }
            else
                FXOR(l,r,0,Max,1);
        }
        query(0,Max,1);
        bool f=0;
        int s=-1,e;//记录答案区间的起点的终点
        for(int i=0;i<=Max;i++){
            if(flag[i]){
                if(s==-1) s=i;
                e=i;
            }
            else{
                if(s!=-1){
                    if(f) printf(" ");
                    f=1;
                    printf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,e&1?')':']');//判断区间的起点的终点的奇偶性,分别对应开区间和闭区间
                    s=-1;//由于最开始乘2了,所以最后要除2.
                }
            }
        }
        if(!f) printf("empty set");
        puts("");
        return 0;
    }


  • 相关阅读:
    Hibernate学习笔记(一)
    mysql内联接、左联接、右联接
    mysql表数据增删改查、子查询
    mysql建表时候的五种约束
    mysql数据库基本数据类型
    nginx uwsgi flask相关配置
    关于爬虫数据的解析器设计
    Redis 七月小说网的爬虫缓存设计
    MariaDB 数据库迁移
    React Relay 实现
  • 原文地址:https://www.cnblogs.com/Levi-0514/p/9092860.html
Copyright © 2020-2023  润新知