bzoj 3226: [Sdoi2008]校门外的区间(线段树)
2016-09-16 11:09
453 查看
3226: [Sdoi2008]校门外的区间
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 307
[Submit][Status][Discuss]
Description
[align=left] [/align]受校门外的树这道经典问题的启发,A君根据基本的离散数学的知识,抽象出5种运算维护集合S(S初始为空)并最终输出S。现在,请你完成这道校门外的树之难度增强版——校门外的区间。
5种运算如下:
[align=center]U T[/align] | [align=center]S∪T[/align] |
[align=center]I T[/align] | [align=center]S∩T[/align] |
[align=center]D T[/align] | [align=center]S-T[/align] |
[align=center]C T[/align] | [align=center]T-S[/align] |
[align=center]S T[/align] | [align=center]S⊕T[/align] |
基本集合运算如下:
[align=center]A∪B[/align] | [align=center]{x : xÎA or xÎB}[/align] |
[align=center]A∩B[/align] | [align=center]{x : xÎA and xÎB}[/align] |
[align=center]A-B[/align] | [align=center]{x : xÎA and xÏB}[/align] |
[align=center]A⊕B[/align] | [align=center](A-B)∪(B-A)[/align] |
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≤70000Source
线段树[Submit][Status][Discuss]
题解:线段树。
因为有开闭区间之分,所以我们对于在每个数之间加一个点,让所有开区间的操作作用在中间点上。
五种集合操作
S∪T 直接在T区间打1标记。
S∩T 求并集,所以将T区间以外的区域清零即可
S-T
将T区间清零
T-S
将T区间以外的区域清零,在将T区间内的点取反即可。
S⊕T
这个操作就是除去S,T的并集,所以直接将T区间内的点取反即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 200003
using namespace std;
int n,m,tr[N*4],delta[N*4],rev[N*4],pos[N*2];
char s[100],cl,cr;
struct data
{
int x,y,opt;
}a
;
void solve(int now)
{
rev[now]^=1;
if (delta[now]&&rev[now])
rev[now]=0,delta[now]=(delta[now]==1?2:1);
tr[now]=(tr[now]==1?0:1);
}
void pushdown(int now,int l,int r)
{
if (delta[now]==1)
{
delta[now<<1]=delta[now<<1|1]=delta[now];
rev[now<<1]=rev[now<<1|1]=0;
tr[now<<1]=tr[now<<1|1]=1;
delta[now]=0; rev[now]=0;
}
else
if (delta[now]==2)
{
delta[now<<1]=delta[now<<1|1]=delta[now];
rev[now<<1]=rev[now<<1|1]=0;
tr[now<<1]=tr[now<<1|1]=0;
delta[now]=0; rev[now]=0;
}
if (rev[now])
{
solve(now<<1); solve(now<<1|1);
rev[now]=0;
}
}
void update(int x)
{
tr[x]=tr[x<<1]&&tr[x<<1|1];
}
void qjchange(int now,int l,int r,int ll,int rr,int v)
{
if (ll>rr) return;
if (ll<=l&&r<=rr)
{
delta[now]=v; rev[now]=0;
if (v==1) tr[now]=1;
else tr[now]=0;
return ;
}
int mid=(l+r)/2;
pushdown(now,l,r);
if (ll<=mid) qjchange(now<<1,l,mid,ll,rr,v);
if (rr>mid) qjchange(now<<1|1,mid+1,r,ll,rr,v);
update(now);
}
void reserve(int now,int l,int r,int ll,int rr)
{
if (ll>rr) return;
if (ll<=l&&r<=rr)
{
rev[now]^=1;
if (delta[now]&&rev[now])
rev[now]=0,delta[now]=(delta[now]==1?2:1);
tr[now]=(tr[now]==1?0:1);
return;
}
int mid=(l+r)/2;
pushdown(now,l,r);
if (ll<=mid) reserve(now<<1,l,mid,ll,rr);
if (rr>mid) reserve(now<<1|1,mid+1,r,ll,rr);
update(now);
}
int find(int now,int l,int r,int x)
{
if (l==r) return tr[now];
pushdown(now,l,r);
int mid=(l+r)/2;
if (x<=mid) return find(now<<1,l,mid,x);
else return find(now<<1|1,mid+1,r,x);
}
int main()
{
int x,y;
while (scanf("%s %c%d,%d%c",s,&cl,&x,&y,&cr)!=EOF)
{
n++;
if (s[0]=='U') a
.opt=1;
if (s[0]=='I') a
.opt=2;
if (s[0]=='D') a
.opt=3;
if (s[0]=='C') a
.opt=4;
if (s[0]=='S') a
.opt=5;
if (cl=='[') a
.x=2*x;
else a
.x=2*x+1;
if (cr==']') a
.y=2*y;
else a
.y=2*y-1;
m=max(m,2*y);
}
for (int i=1;i<=n;i++)
{
if (a[i].opt==1)
qjchange(1,0,m,a[i].x,a[i].y,1);
if (a[i].opt==2)
qjchange(1,0,m,0,a[i].x-1,2),qjchange(1,0,m,a[i].y+1,m,2);
if (a[i].opt==3)
qjchange(1,0,m,a[i].x,a[i].y,2);
if (a[i].opt==4)
qjchange(1,0,m,0,a[i].x-1,2),qjchange(1,0,m,a[i].y+1,m,2),
reserve(1,0,m,a[i].x,a[i].y);
if (a[i].opt==5)
reserve(1,0,m,a[i].x,a[i].y);
}
bool f=false;
for (int i=0;i<=m;i++)
{
pos[i]=find(1,0,m,i);
if (pos[i]) f=true;
}
int i=0;
while (i<=m)
{
while (pos[i]==0&&i<=m) i++;
if (pos[i]==0) break;
int j=i;
while (pos[j]==1) j++;
j--;
if (i%2==0) printf("[%d,",i/2);
else printf("(%d,",i/2);
if (j%2==0) printf("%d] ",j/2);
else printf("%d) ",j/2+1);
i=j+1;
}
if (!f) printf("empty set\n");
}
相关文章推荐
- [bzoj3226][Sdoi2008]校门外的区间——线段树
- BZOJ 题目 3226: [Sdoi2008]校门外的区间(线段树区间交并差异或)
- bzoj 3226 [Sdoi2008]校门外的区间(线段树)
- [BZOJ]3226: [Sdoi2008]校门外的区间 线段树
- bzoj3226: [Sdoi2008]校门外的区间 线段树
- [线段树 标记] BZOJ 3226 [Sdoi2008]校门外的区间
- [BZOJ3226][SDOI2008]校门外的区间(线段树)
- 【SDOI2008】【BZOJ3226】校门外的区间
- 【分块】bzoj3226 [Sdoi2008]校门外的区间
- BZOJ-3226 [SDOI2008]校门外的区间
- 【BZOJ】【P3226】【Sdoi2008】【校门外的区间】【题解】【线段树】
- BZOJ 3226: [Sdoi2008]校门外的区间
- BZOJ 3226 [SDOI2008]校门外的区间
- 3226: [Sdoi2008]校门外的区间 线段树
- bzoj 3226: [Sdoi2008]校门外的区间
- 【bzoj3226】[Sdoi2008]校门外的区间
- 3226: [Sdoi2008]校门外的区间
- 「BZOJ3226」[SDOI2008] 校门外的区间(线段树好题)
- 【BZOJ3226】【codevs2297】校门外的区间,线段树
- 3226: [Sdoi2008]校门外的区间