poj 3225 区间

poj的中文题哦

果然不是容易写的

光是几个运算符就很让人 头疼

我们来看一看

这里写图片描述

让求最后集合里的数。

可这么多运算怎么弄

需要转换一下喽
一开始有一个大的区间0-maxn
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互换‘

所以问题演变成覆盖和xor的线段树嗯哼!

但是第一次写 越界问题没有注意。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 666666
//#define maxn 10<<1 
using namespace std;
//by mars_ch
//感谢SiriusRen爸爸
/*
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互换
*/
int cover[maxn<<2];//覆盖标记
int rev[maxn<<2];//翻转 
int vis[maxn<<2];
void pushdown(int x)
{
    if(cover[x]!=-1)
    {
        cover[x*2]=cover[x*2+1]=cover[x];
        rev[x*2]=rev[x*2+1]=0;
        cover[x]=-1;//完成覆盖标记 
    }
    if(rev[x])
    {
        if(cover[x*2]!=-1) cover[x*2]^=1;
        else rev[x*2]^=1;
        rev[x]=0;

         if(cover[x*2+1]!=-1) cover[x*2+1]^=1;
        else rev[x*2+1]^=1;
        rev[x]=0;
    }
}
void updata(int op,int L,int R,int l,int r,int num)
{
    //printf("%d %d %d %d\n",l,r,L,R);
    if(l<L || r>R) return;
    //printf("twice %d %d %d %d\n",l,r,L,R);
    //printf(" llalaal\n");
    if(l == L && r ==R)
    {
        if(op!=-1)//不是覆盖操作 ,当一个节点得到覆盖标记后,翻转标记清空 
        {
            //printf("%d %d %d %d\n",num,op,l,r);
            cover[num]=op;
            rev[num]=0; 
        }
        else
        {
            if(cover[num]!=-1) cover[num]^=1;    //如果区间都是0或者1那就直接改变覆盖 
            else rev[num]^=1;   //不然该翻转标记 
        }
        return;
    }
    pushdown(num);
    int mid=(L+R)/2;
    if(r<=mid) updata(op,L,mid,l,r,num*2);
    else if(l>mid) updata(op,mid+1,R,l,r,num*2+1);//l>mid不是>=
    else
    {
        updata(op,L,mid,l,mid,num*2);
        updata(op,mid+1,R,mid+1,r,num*2+1);
    }
}
void query(int l,int r,int x)
{
    if(cover[x] == 1)
    {
        for(int i=l;i<=r;i++)
        {
            vis[i]=true;
        }
        return ;
    }
    else if(cover[x] == 0) return;
    if(l == r) return ;
    pushdown(x);
    int mid=(l+r)/2;
    query(l,mid,x*2);
    query(mid+1,r,x*2+1);
}

int main()
{
    char c;
    char b,d;
    int x,y;
    while(scanf("%c %c%d,%d%c\n",&c,&b,&x,&y,&d)!=EOF)
    {
        x*=2,y*=2;
        if(b == '(') x++;
        if(d == ')') y--;
        if(x>y)x=y=150000;       //非法情况
        //printf("%d %d\n",x,y); 
        if( c == 'U') updata(1,0,maxn,x,y,1);
        else if(c == 'D') updata(0,0,maxn,x,y,1);
        else if(c == 'I') 
        {
            if(x)updata(0,0,maxn,0,x-1,1);   //数组越界
            updata(0,0,maxn,y+1,maxn,1);
        }
        else if(c == 'C')
        {
            if(x)updata(0,0,maxn,0,x-1,1);
            updata(0,0,maxn,y+1,maxn,1);
            updata(-1,0,maxn,x,y,1);
        }
        else if(c == 'S')
        {
            updata(-1,0,maxn,x,y,1);
        }
    }
    query(0,maxn,1);
    /*for(int i=0;i<=20;i++)
    {
        printf("%d ",vis[i]);
    }
    puts("");*/
    int s=-1,e;
    bool flag=0;
    for(int i=0;i<=146666;i++)
    {
        if(vis[i])
        {
            if(s == -1)
            {
                s=i;
            }
            e=i;
        }
        else
        {
            if(s == -1) continue;
            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\n");
    else puts("");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值