POJ 3225 区间
Posted bzmd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3225 区间相关的知识,希望对你有一定的参考价值。
Description
LogLoader是一家专门提供日志分析产品的公司。Ikki在做毕业设计的同时,还忙于在LogLoader做实习。在他的工作里,有一项是要写一个模块来处理时间区间。这个事情一直让他感到很迷糊,所以现在他很需要你帮忙。
在离散数学里面,你已经学习了几种基本的集合运算,具体地说就是并、交、相对补和对称差。它们自然地也适用于区间这种特殊的集合。作为你的快速参考,它们可以总结成下表:
运算 记号 定义
并 A ∪ B {x : x ∈ A或x ∈ B} 交 A ∩ B {x : x ∈ A并x ∈ B} 相对补 A ? B {x : x ∈ A但是x ?B} 对称差 A ⊕ B (A ? B) ∪ (B ? A)
Ikki已经把他的工作里出现的区间运算抽象成一个很小的编程语言。他想你为他实现一个解析器。这个语言维护一个集合S。S一开始是空集,并根据下列命令被修改:
命令 语义 U
TS ← S ∪ T I
TS ← S ∩ T D
TS ← S ? T C
TS ← T ? S S
TS ← S ⊕ T
Input
输入包含一组测试数据,由0到65,535条命令组成。每条命令占一行,形式如下:
X
T
其中X
是‘U
’、‘I
’、‘D
’、‘C
’和‘S
’中的一个,T是一个区间,
形式为(
a,
b)
、(
a,
b]
、[
a,
b)
和[
a,
b]
之一(a, b ∈ Z; 0 ≤ a ≤ b ≤ 65,535),取它们通常的意义。命令按在输入中出现的顺序执行。
文件结束符(EOF)表示输入结束。
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)
Source
Translator
U T:[a,b]覆盖为1.
I T:[0,a-1] [b+1,maxn] 覆盖为0
D T:[a,b]覆盖为0
C T:[0,a-1] [b+1,maxn] 覆盖为0,[a,b]取反
S T:[a,b]取反
最后输出时我们查询每一个点的值就可以了
#include<cstdio> #define ls x<<1 #define rs x<<1|1 const int N=131070; int tr[N<<2],lz1[N<<2];//lz1标记表示的是 bool lz2[N<<2+5]; char c1,c2,c3; void pu(int x) { if(tr[ls]==2||tr[rs]==2||tr[ls]+tr[rs]==1) tr[x]=2;//只要有一边2,就是混合或者两边有一边为1,另边为0 else if(tr[ls]&tr[rs]) tr[x]=1; else tr[x]=0; } void cl(int x) { if(lz1[x]) ++lz1[x],tr[x]=tr[x]==0;对于 else { lz2[x]=lz2[x]==0; if(tr[x]<2) tr[x]=tr[x]==0; } } void pd(int l,int r,int x,int mid) { if(lz1[x]) { lz1[ls]=lz1[rs]=lz1[x]; lz2[ls]=lz2[rs]=0; tr[ls]=tr[rs]=lz1[x]&1; lz1[x]=0; } if(lz2[x]) cl(ls),cl(rs); lz2[x]=0; } void chan(int l,int r,int x,int ql,int qr,int a) { if(ql>qr) return; if(ql<=l&&qr>=r) { tr[x]=a; lz2[x]=0; lz1[x]=a+2; } else { int mid=(l+r)>>1; pd(l,r,x,mid); if(ql<=mid) chan(l,mid,ls,ql,qr,a); if(qr>mid) chan(mid+1,r,rs,ql,qr,a); pu(x); } } void fan(int l,int r,int x,int ql,int qr) { if(ql>qr) return; if(ql<=l&&qr>=r) cl(x); else { int mid=(l+r)>>1; pd(l,r,x,mid); if(ql<=mid) fan(l,mid,ls,ql,qr); if(qr>mid) fan(mid+1,r,rs,ql,qr); pu(x); } } int ask(int l,int r,int x,int wz) { if(l==r) return tr[x]; else { int mid=(l+r)>>1; pd(l,r,x,mid); return wz<=mid?ask(l,mid,ls,wz):ask(mid+1,r,rs,wz); } } int main() { int l,r,sf=0; while(scanf("%c %c%d,%d%c ",&c1,&c2,&l,&r,&c3)!=EOF) { l<<=1; r<<=1; if(c2==‘(‘) ++l; if(c3==‘)‘) --r; if(c1==‘U‘) chan(0,N,1,l,r,1); else if(c1==‘S‘) fan(0,N,1,l,r); else if(c1==‘D‘) chan(0,N,1,l,r,0); else { if(l>0) chan(0,N,1,0,l-1,0); if(r<N) chan(0,N,1,r+1,N,0); if(c1==‘C‘) fan(0,N,1,l,r); } } l=0; for(int i=0;i<=N;++i) if(ask(0,N,1,i)) ++l; else if(l) { if(sf) putchar(‘ ‘); int ll=i-l,rr=i; l=0; printf("%c%d,%d%c",ll&1?‘(‘:‘[‘,ll>>1,rr>>1,rr&1?‘]‘:‘)‘); sf=1; } if(l) { if(sf) putchar(‘ ‘); sf=1; int ll=N-l+1,rr=N+1; printf("%c%d,%d%c",ll&1?‘(‘:‘[‘,ll>>1,rr>>1,rr&1?‘]‘:‘)‘); } if(!sf) printf("empty set"); return 0; }
以上是关于POJ 3225 区间的主要内容,如果未能解决你的问题,请参考以下文章
poj 3225 Help with Intervals(线段树,区间更新)