BZOJ 题目 3226: [Sdoi2008]校门外的区间(线段树区间交并差异或)

3226: [Sdoi2008]校门外的区间

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 486   Solved: 181
[ Submit][ Status][ Discuss]

Description

 
  受校门外的树这道经典问题的启发,A君根据基本的离散数学的知识,抽象出5种运算维护集合S(S初始为空)并最终输出S。现在,请你完成这道校门外的树之难度增强版——校门外的区间。
 
  5种运算如下:
U T
S∪T
I T
S∩T
D T
S-T
C T
T-S
S T
S⊕T
 
  基本集合运算如下:
A∪B
{x : xÎA or xÎB}
A∩B
{x : xÎA and xÎB}
A-B
{x : xÎA and xÏB}
A⊕B
(A-B)∪(B-A)
 

Input

  输入共M行。
  每行的格式为X T,用一个空格隔开,X表示运算的种类,T为一个区间(区间用(a,b), (a,b], [a,b), [a,b]表示)。
 

Output

 
  共一行,即集合S,每个区间后面带一个空格。若S为空则输出"empty set"。
 

Sample Input

U [1,5]
D [3,3]
S [2,4]
C (1,5)
I (2,3]

Sample Output

(2,3)

HINT

对于 100% 的数据,0≤a≤b≤65535,1≤M≤70000

Source

线段树

用getchar()re,。。

ac代码

/**************************************************************
    Problem: 3226
    User: kxh1995
    Language: C++
    Result: Accepted
    Time:548 ms
    Memory:6948 kb
****************************************************************/
 
#include<stdio.h>
#include<string.h>
#define maxn 131072
struct s
{
    int cover,Xor;
}node[maxn<<2];
int hash[maxn<<2];
void fxor(int tr)
{
    if(node[tr].cover!=-1)
        node[tr].cover^=1;
    else
        node[tr].Xor^=1;
}
void pushdown(int tr)
{
    if(node[tr].cover!=-1)
    {
        node[tr<<1].cover=node[tr<<1|1].cover=node[tr].cover;
        node[tr<<1].Xor=node[tr<<1|1].Xor=0;
        node[tr].cover=-1;
    }
    if(node[tr].Xor)
    {
        fxor(tr<<1);
        fxor(tr<<1|1);
        node[tr].Xor=0;
    }
}
void update(char op,int L,int R,int l,int r,int tr)
{
    if(L<=l&&r<=R)
    {
        if(op=='U')
        {
            node[tr].cover=1;
            node[tr].Xor=0;
        }
        else
            if(op=='D')
            {
                node[tr].cover=0;
                node[tr].Xor=0;
            }
            else
                if(op=='C'||op=='S')
                    fxor(tr);
                return;
    }
    pushdown(tr);
    int mid=(l+r)>>1;
    if(L<=mid)
    {
        update(op,L,R,l,mid,tr<<1);
    }
    else
    {
        if(op=='I'||op=='C')
            node[tr<<1].Xor=node[tr<<1].cover=0;
    }
    if(mid<R)
    {
        update(op,L,R,mid+1,r,tr<<1|1);
    }
    else
    {
        if(op=='I'||op=='C')
            node[tr<<1|1].Xor=node[tr<<1|1].cover=0;
    }
}
void query(int l,int r,int tr)
{
    if(node[tr].cover==1)
    {
        for(int i=l;i<=r;i++)
            hash[i]=1;
        return;
    }
    else
        if(node[tr].cover==0)
            return;
        if(l==r)
            return;
        pushdown(tr);
        int mid=(l+r)>>1;
        query(l,mid,tr<<1);
        query(mid+1,r,tr<<1|1);
}
int main()
{
    node[1].cover=node[1].Xor=0;
    char op,a,b;
    int x,y;
    while(scanf("%c %c%d,%d%c\n",&op,&a,&x,&y,&b)!=EOF)
    {
        x<<=1;
        y<<=1;
        if(a=='(')
            x++;
        if(b==')')
            y--;
        if(x>y)
        {
            if(op=='I'||op=='C')
            {
                node[1].cover=node[1].Xor=0;
            }
        }
        update(op,x,y,0,maxn,1);
    }
    query(0,maxn,1);
    int s=-1,t,flag=0;
    for(int i=0;i<=maxn;i++)
    {
        if(hash[i])
        {
            if(s==-1)
                s=i;
            t=i;
        }
        else
        {
            if(s!=-1)
            {
                if(flag==1)
                    printf(" ");
                flag=1;
                if(s&1)
                    a='(';
                else
                    a='[';
                if(t&1)
                    b=')';
                else
                    b=']';
                printf("%c%d,%d%c",a,s>>1,(t+1)>>1,b);
                    s=-1;
            }
        }
    }
    if(flag==0)
        printf("empty set\n");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值