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");
}