成段异或更新 poj3255 Help with Intervals

题目链接  poj3255 Help with Intervals

题目大意:集合的基本操作,具体地说就是并、交、相对补和对称差。五种操作 U’、‘I’、‘D’、‘C’和‘S’中的一个 加上一个区间(T)形式为(a,b)(a,b][a,b)[a,b]。

解题思路:  U:把区间[l,r]覆盖成1;      I:把区间把[-∞,l)(r,∞]覆盖成0;     D:把区间[l,r]覆盖成0。

                      C:把区间[-∞,l)(r,∞],再对[l,r]区间0/1异或一次。  S:区间[l,r]内0/1异或一次。 

这里要注意的一点就是先覆盖再异或 and 先异或再覆盖的区别了,两者是不同的。

#include<cstdio>
#include<iostream>
#include<cstring>
#define lz l,m,rt<<1
#define rz m+1,r,rt<<1|1
using namespace std;

const int mm=133333;
int col[mm<<2],turn[mm<<2],cov[mm+5];

void T(int rt)
{
    if(col[rt])col[rt]^=3;
    else turn[rt]^=1;
}
void pushdown(int rt)
{
    if(col[rt])
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        col[rt]=turn[rt<<1]=turn[rt<<1|1]=0;
    }
    if(turn[rt])
    {
        T(rt<<1);
        T(rt<<1|1);
        turn[rt]=0;
    }
}
void updata(int L,int R,int op,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        if(op)col[rt]=op,turn[rt]=0;
        else T(rt);
        return;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m)updata(L,R,op,lz);
    if(R>m)updata(L,R,op,rz);
}
void query(int l,int r,int rt)
{
    if(col[rt])
    {
        if(col[rt]<2)
            for(int i=l; i<=r; ++i)cov[i]=1;
        return;
    }
    if(l==r)return;
    pushdown(rt);
    int m=(l+r)>>1;
    query(lz);
    query(rz);
}
int main()
{
    char op,l,r;
    int i,a,b,flag;
    updata(0,mm,2,0,mm,1);
    while(~scanf("%c %c%d,%d%c\n",&op,&l,&a,&b,&r))
    {
        a=(a<<1)+(l=='(');
        b=(b<<1)-(r==')');
        if(a>b)
        {
            if(op=='I'||op=='C')updata(0,mm,2,0,mm,1);
        }
        else
        {
            if(op=='U')updata(a,b,1,0,mm,1);
            if(op=='I'||op=='C')
            {
                if(a>0)updata(0,a-1,2,0,mm,1);
                if(b<mm)updata(b+1,mm,2,0,mm,1);
            }
            if(op=='D')updata(a,b,2,0,mm,1);
            if(op=='C'||op=='S')updata(a,b,0,0,mm,1);
        }
    }
    memset(cov,0,sizeof(cov));
    query(0,mm,1);
    for(a=b=-1,flag=i=0; i<=mm; ++i)
        if(cov[i])b=i,a=a<0?i:a;
        else if(a>=0)
        {
            if(flag)printf(" ");
            flag=1;
            printf("%c%d,%d%c",a&1?'(':'[',a>>1,(b+1)>>1,b&1?')':']');
            a=b=-1;
        }
    if(!flag)printf("empty set");
    puts("");
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值