• 线段树 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;
    }
  • 相关阅读:
    20201206贪心法1总结
    20201105枚举课后总结
    【题解】P1057 传球游戏
    人生哲理100句整理
    [计蒜客]棋子等级 题解
    整式的乘法相关公式(随着后续学习持续更新)
    计算几何公式(随着后续学习持续更新)
    mybatis中foreach在不同场景下的使用整理
    Java导出Excel文件详解
    java单元测试
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6196319.html
Copyright © 2020-2023  润新知