您的位置:首页 > 其它

BZOJ3226 [Sdoi2008]校门外的区间

2017-04-13 15:30 309 查看

BZOJ3226 [Sdoi2008]校门外的区间 线段树

Description

抽象出5种运算维护集合S(S初始为空)并最终输出S

输入操作
U TS∪T
I TS∩T
D TS-T
C TT-S
S TS⊕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

题解

可以发现,a,b,其实很小。而且这些集合的操作都是区间操作,就可以用线段树来维护。因为有开或闭区间,我们可以把a,b,放大2倍,相当与再x与x+1之间加一个x+0.5。这样就可以很好地处理开,闭区间问题。

U :区间内更改为1

I:区间外更改为0

D:区间内更改为0

C:区间外更改为0,区间内取反

S:区间内取反

我这里mark为修改标记,rev为取反标记。

再pushdown时注意一下顺序。

本入代码奇丑无比,不喜勿喷

#include <cstdio>
#include <iostream>
#include <cmath>
#include <stack>
#include <algorithm>
#include <cstring>
#include <climits>
#define MAXN 131070+10
#define LL long long
using namespace std;
bool num[MAXN<<2],ans[MAXN<<2];
int n=MAXN,m,mark[MAXN<<2],rev[MAXN<<2];
void build(int rt,int l,int r)
{
num[rt]=0;mark[rt]=-1;
if(l==r) return ;
build(rt<<1,l,l+r>>1);
build(rt<<1|1,(l+r>>1)+1,r);
}
void pushdown(int rt,int l,int r)
{
if(mark[rt]!=-1||rev[rt])
{
if(l==r)
{
if(mark[rt]!=-1) num[rt]=mark[rt];
if(rev[rt]) num[rt]^=rev[rt];
}else
{
if(mark[rt]!=-1)
{
mark[rt<<1]=mark[rt<<1|1]=mark[rt];
rev[rt<<1]=rev[rt<<1|1]=0;
}
rev[rt<<1]^=rev[rt];rev[rt<<1|1]^=rev[rt];
}
rev[rt]=0;mark[rt]=-1;
}
}
void update(int L,int R,int k,int l,int r,int rt)
{

pushdown(rt,l,r);
if(L<=l&&r<=R)
{
if(k!=2) mark[rt]=k;
else rev[rt]^=1;
return ;
}
int m=(l+r)>>1;
if(L<=m) update(L,R,k,l,m,rt<<1);
if(R>m) update(L,R,k,m+1,r,rt<<1|1);
}
int query(int x,int l,int r,int rt)
{
pushdown(rt,l,r);
if(l==r) return num[rt];
int m=(l+r)>>1;
if(x<=m) return query(x,l,m,rt<<1);
if(x>m) return query(x,m+1,r,rt<<1|1);
}
int main()
{
build(1,0,n);
char k[4],l,r;int a,b;
while(scanf("%s ",k)!=EOF)
{
scanf("%c",&l);
scanf("%d,%d",&a,&b);
scanf("%c",&r);
if(l=='(') a=a*2+1; else a=a*2;
if(r==')') b=b*2-1; else b=b*2;
if(k[0]=='U') update(a,b,1,0,n,1);
else if(k[0]=='I')  update(1,a-1,0,0,n,1),update(b+1,n,0,0,n,1);
else if(k[0]=='D')  update(a,b,0,0,n,1);
else if(k[0]=='C')  update(1,a-1,0,0,n,1),update(b+1,n,0,0,n,1),update(a,b,2,0,n,1);
else if(k[0]=='S')  update(a,b,2,0,n,1);
}
int flag=0;
for(int i=0;i<=n;i++)
{
ans[i]=query(i,0,n,1);
if(!flag&&ans[i]==1) flag=1;
}
if(flag==0) {printf("empty set\n");return 0;}
int be=-1,e=1;
for(int i=0;i<=n+1;i++)
{
if(ans[i]==1)
{
if(be==-1) be=i;
}else
{
if(ans[i-1]==1)
{
e=i-1;
if(be&1) printf("(%d,",be/2);
else printf("[%d,",be/2);
if(e&1) printf("%d) ",(e+1)/2);
else printf("%d] ",e/2);
be=-1;e=0;
}
}
}
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: