zoukankan      html  css  js  c++  java
  • 线段树 poj3225

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

    因为普通的线段树实际处理的并非真正的区间,而是一系列点,相当于处理一个向量。这个问题需要处理的是真正的区间,所以应该有一个主导思想就是,把区间点化!不知哪位大牛搞了一个倍增区间出来,实在佩服!对于待处理区间[a,b](暂时不考虑开闭),对其边界均乘2。若区间左开则对左界值+1,若区间右开,则对右界-1!

        如:[2,3]会倍增为[4,6],[2,3)会倍增为[4,5],(2,3]会倍增为[5,6],(2,3)将倍增为[5,5],我们这时可以看到,对于普通线段树无法处理的线段如(x,x+1)将被点化为[2*x+1,2*x+1]!这个问题得到比较完美的解决

    最后把查找出来的区间逆向倍增操作一下,就可以得到实际的区间以及起开闭情况!

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    
    using namespace std;
    
    #define MAXN1 65545<<1
    #define MAXN  65535<<1
    
    int x[MAXN<<4],col[MAXN<<4];
    
    void FXOR(int a)
    {
        if(x[a]!=-1)
            x[a]^=1;
        else
            col[a]^=1;
    }
    void push_down(int a)
    {
        if(x[a]!=-1)
        {
            x[a<<1]=x[a<<1|1]=x[a];
            col[a<<1]=col[a<<1|1]=0;
            x[a]=-1;
        }
        if(col[a])
        {
            FXOR(a<<1);
            FXOR(a<<1|1);
            col[a]=0;
        }
    }
    
    void update(char val,int l,int r,int a1,int b1,int a)
    {
        if(l>=a1&&b1>=r)
        {
            if(val=='U')
            {
                x[a]=1;
                col[a]=0;
            }
            else if(val=='D')
            {
                x[a]=0;
                col[a]=0;
            }
            else if(val=='S'||val=='C')
                FXOR(a);
            return ;
        }
        push_down(a);
        int mid=(l+r)>>1;
        if(a1<=mid)
            update(val,l,mid,a1,b1,a<<1);
        else if(val=='I'||val=='C')
            x[a<<1]=col[a<<1]=0;
        if(b1>mid)
            update(val,mid+1,r,a1,b1,a<<1|1);
        else if(val=='I'||val=='C')
            x[a<<1|1]=col[a<<1|1]=0;
    }
    bool vis[MAXN1];
    void Query(int l,int r,int a)
    {
        if(x[a]==1)
        {
            for(int i=l;i<=r;i++)
                vis[i]=1;
            return ;
        }
        else if(x[a]==0)
            return ;
        if(l==r)
            return ;
        push_down(a);
        int mid=(l+r)>>1;
        Query(l,mid,a<<1);
        Query(mid+1,r,a<<1|1);
    }
    int main()
    {
        x[1]=col[1]=0;
        char a,a1,a2,b;
        int l,r;
        while(scanf("%c %c%d,%d%c%c",&a,&a1,&l,&r,&a2,&b)!=EOF)
        {
            l<<=1;
            r<<=1;
            if(a1=='(')
                l++;
            if(a2==')')
                r--;
            if(l>r)
                continue;
            update(a,0,MAXN,l,r,1);
        }
        Query(0,MAXN,1);
        int s=-1,e;
        bool flag=0;
        for(int i=0;i<=MAXN;i++)
        {
            if(vis[i])
            {
                if(s==-1)
                    s=i;
                e=i;
            }
            else
            {
                if(s!=-1)
                {
                    if(flag)printf(" ");
                    printf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,e&1?')':']');
                    s=-1;
                    flag=1;
                }
            }
        }
        if(!flag)
            printf("empty set");
    
        return 0;
    }
  • 相关阅读:
    Apache Ant 1.9.1 版发布
    Apache Subversion 1.8.0rc2 发布
    GNU Gatekeeper 3.3 发布,网关守护管理
    Jekyll 1.0 发布,Ruby 的静态网站生成器
    R语言 3.0.1 源码已经提交到 Github
    SymmetricDS 3.4.0 发布,数据同步和复制
    beego 0.6.0 版本发布,Go 应用框架
    Doxygen 1.8.4 发布,文档生成工具
    SunshineCRM 20130518发布,附带更新说明
    Semplice Linux 4 发布,轻量级发行版
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6196319.html
Copyright © 2011-2022 走看看