【SDOI2008】【BZOJ3226】校门外的区间

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

线段树

把那五种操作全都看成区间0,1赋值或者取反
一个点拆成两个奇偶区分开区间闭区间.
自己看代码体会一下吧
这题思路不难写起来真的是有点蛋疼T_T
调了俩小时

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 140000
#define lchild rt<<1,l,mid
#define rchild rt<<1|1,mid+1,r
#define ln rt<<1
#define rn rt<<1|1
using namespace std;
int n;
char ch[30];
int ans[MAXN];
struct seg
{
    int l,r,cov,rev;
}tree[MAXN<<2];
void push_down(int rt)
{
    if (tree[rt].cov!=-1)   tree[ln].cov=tree[rt].cov,tree[ln].rev=0,tree[rn].cov=tree[rt].cov,tree[rn].rev=0;
    if (tree[rt].rev)
    {
        if (tree[ln].cov!=-1)   tree[ln].cov^=1;    else    tree[ln].rev^=1;
        if (tree[rn].cov!=-1)   tree[rn].cov^=1;    else    tree[rn].rev^=1;
    }
    tree[rt].rev=0;tree[rt].cov=-1;
}
void build(int rt=1,int l=0,int r=n)
{
    tree[rt].l=l;tree[rt].r=r;tree[rt].cov=-1;
    if (l==r)   return;
    int mid=(l+r)>>1;build(lchild);build(rchild);
}
void modify_cov(int rt,int l,int r,int delta)
{
    int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;
    if (l>r)    return;
    if (l<=L&&r>=R) {tree[rt].cov=delta;tree[rt].rev=0;return;}
    push_down(rt);
    if (r<=mid) modify_cov(ln,l,r,delta);
    else
    if (l>mid)  modify_cov(rn,l,r,delta);
    else    modify_cov(ln,l,mid,delta),modify_cov(rn,mid+1,r,delta);
}
void modify_rev(int rt,int l,int r)
{
    int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;
    if (l>r)    return;
    if (l<=L&&r>=R)
    {
        if (tree[rt].cov!=-1)   tree[rt].cov^=1;
        else    tree[rt].rev^=1;    return;
    }
    push_down(rt);
    if (r<=mid) modify_rev(ln,l,r);
    else
    if (l>mid)  modify_rev(rn,l,r);
    else    modify_rev(ln,l,mid),modify_rev(rn,mid+1,r);
}
void solve(int rt)
{
    int L=tree[rt].l,R=tree[rt].r;
    if (L==R)
    {
        if (tree[rt].cov!=-1)   ans[L]=tree[rt].cov;
        else    ans[L]=tree[rt].rev;    return;
    }
    push_down(rt);solve(ln);solve(rn);
}
int main()
{
    n=MAXN-1;build();
    while (scanf("%s",ch)!=EOF)
    {
        char c=getchar();int flag,l,r;
        while (c!='('&&c!='[')  c=getchar();flag=(c=='(');
        scanf("%d",&l);l=(l<<1)+flag;c=getchar();scanf("%d",&r);c=getchar();flag=-(c!=']');r=(r<<1)+flag;
        if (l>r)    continue;
        if (ch[0]=='U') modify_cov(1,l,r,1);
        if (ch[0]=='I') modify_cov(1,0,l-1,0),modify_cov(1,r+1,n,0);
        if (ch[0]=='D') modify_cov(1,l,r,0);
        if (ch[0]=='C') modify_cov(1,0,l-1,0),modify_cov(1,r+1,n,0),modify_rev(1,l,r);
        if (ch[0]=='S') modify_rev(1,l,r);
    }
    solve(1);int pos=0,flag=0;
    for (int i=0;i<=n;i=pos+1)
    {
        pos=i;
        if (!ans[i])    continue;
        if (flag)   printf(" ");flag=1;
        while (ans[pos+1])  pos++;
        if (i&1)    printf("(%d,",i>>1);
        else    printf("[%d,",i>>1);
        if (pos&1)  printf("%d)",(pos+1)>>1);
        else    printf("%d]",pos>>1);
    }
    if (!flag)  puts("empty set");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值