线段树 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;
}

 

posted on 2016-12-19 09:34  HelloWorld!--By-MJY  阅读(172)  评论(0编辑  收藏  举报

导航