题目链接:http://poj.org/problem?id=3225
思路:
采用线段树,对线段区间进行0,1标记表示该区间是否包含在集合s内
U T S ← S ∪ T 即将[l,r]标记为1
I T S ← S ∩ T 即将-oo~l和r~+oo标记为0,因为是并集,所以并集后的集合s一定在[l,r]内,则在l,r内的集合被标记是什么状态就是什么状态(表示是否属于s),[l,r]外的集合不属于s所以标记为0
D T S ← S - T 即将[l,r]标记为0,则在[l,r]内被s包含的集合也会标记为0表示不再属于s
C T S ← T - S 即先将-oo~l,r~+oo标记为0,这部分不属于[l,r]则一定不属于s,然后将[l,r]的标记0/1互换,因为属于s的不再属于s,不属于s的将属于s
S T S ← S ⊕ T 即属于s的不变,[l,r]中不属于s的(区间)0标记为1,属于s的(区间)1标记为0,所以[l,r]的标记0/1互换
最后对区间l,r标记时标记将l*2,r*2标记,如果是闭区间则对l*2+1,或r*2-1进行标记,则输出的时候只需判断奇偶就能判断开闭区间
终于调通了,拿各组数据测试和 HH 大牛的代码比较运行结果都没问题。为此还用 python 写了一段用于随机生成测试数据的代码。提交到POJ上TLE了。于是自己生成大数据自己比较时间,发现的确是比 HH 大牛的代码慢,但不知道怎么优化。。。
我的 TLE 的代码:
///2014.6.5 - 2014.6.7
///poj3225
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define maxn 131072
bool segT[maxn<<2];
bool ud[maxn<<2]; //标记该结点向下的节点是否与该结点是相同的状态(都在S中或都不在S中)
bool in[maxn+1];
void build(int l,int r,int rt){
memset(segT,false,sizeof(segT));
memset(in,false,sizeof(in));
memset(ud,true,sizeof(ud));
}
void PushUp(int rt){
if( !ud[rt] ){
segT[rt] = segT[rt<<1] || segT[rt<<1|1];
if( (segT[rt<<1] == segT[rt<<1|1]) && ud[rt<<1] && ud[rt<<1|1] )
ud[rt] = true;
}
}
void PushDown(int rt){
if( ud[rt] ){
segT[rt<<1] = segT[rt<<1|1] = segT[rt];
ud[rt<<1] = ud[rt<<1|1] = true;
ud[rt] = false;
}
}
void convert(int l,int r,int rt){ //取反
if( ud[rt] ){
if( segT[rt] ) segT[rt] = false;
else segT[rt] = true;
return;
}
if( l<=r ){
int m = (l+r)>>1;
convert(lson);
convert(rson);
}
PushUp(rt);
}
void update(int L,int R,char cmd,int l,int r,int rt){
PushDown(rt);
ud[rt] = false;
if( L<=l && r<=R ){
if( cmd == 'U' ) segT[rt] = ud[rt] = true;
if( cmd == 'D' ) segT[rt] = false,ud[rt] = true;
if( cmd == 'C' || cmd == 'S' ) convert(l,r,rt);
PushUp(rt);
return ;
}
if( l==r ) return ;
int m = (l+r)>>1;
if( L<=m ) update(L,R,cmd,lson);
else if( cmd == 'I' || cmd == 'C' ){
PushDown(rt<<1);
segT[rt<<1] = false,ud[rt<<1] = true;
}
if( m+1<=R ) update(L,R,cmd,rson);
else if( cmd == 'I' || cmd == 'C' ){
PushDown(rt<<1|1);
segT[rt<<1|1] = false,ud[rt<<1|1] = true;
}
PushUp(rt);
}
void setIn(int l,int r,int rt){
if( !segT[rt] ) return;
if( ud[rt] ){
for(int i=l ; i<=r ; i++) in[i] = true;
return;
}
if( l == r ) return ;
int m = (l+r)>>1;
setIn(lson);
setIn(rson);
}
int main(){
// freopen("in","r",stdin);
// freopen("out","w",stdout);
build(0,maxn,1);
char cmd,a,b;
int L,R;
while( scanf("%c %c%d,%d%c",&cmd,&a,&L,&R,&b) != EOF ){
if( a=='(' ) L = L<<1|1;
else L = L<<1;
if( b==')' ) R = (R<<1) - 1;
else R = R<<1;
update(L,R,cmd,0,maxn,1);
getchar();
}
if( ! segT[1] ) printf("empty set\n");
else{
memset(in,false,sizeof(in));
bool first = true;
setIn(0,maxn,1);
for(int i=0 ; i<=maxn ; i++){
if( in[i] ){
int j = i ;
for( ; in[j+1] ; j++);
char a,b;
if( i & 1 ) a = '(';
else a = '[';
if( j & 1 ) b = ')';
else b = ']';
if( !first ) printf(" ");
printf("%c%d,%d%c",a,i>>1,(j+1)>>1,b );
i = j+1 ;
first = false;
}
}
printf("\n");
}
return 0;
}
尝试写的用于生成测试数据的 python 代码:
import random
import sys
fileout = open("in","w")
sys.stdout = fileout
cmd = ['U','D','S','C','I']
for i in range(1,65535) :
c = int(random.random() * 100) % 5
a = int(random.random() * 100) % 2
b = int(random.random() * 100) % 2
l = random.randint(0,65535)
r = random.randint(l,65535)
while l>r :
r = int(random.random() * 100)
if a==0 :
a = '('
else :
a = '['
if b==0 :
b = ')'
else :
b = ']'
c = cmd[c]
print c + ' ' + a + str(l) + ',' + str(r) + b
贴上几组测试数据:
(1)
D [27323,28582]
I (48593,49724]
C [52824,58649)
S (62504,63132]
D (6713,17378)
C [64279,64704)
U (43350,55633)
I (13250,61130]
C (8284,32422]
C [37148,52506]
S [36301,40476]
C [57254,58462)
S (6800,8020]
C (39395,42257]
U (40138,60510]
D (57476,59784)
U [40559,60039)
I (14862,39269]
D [17447,53082]
U (18103,35170)
C (54521,54592)
S [10509,37894]
U [46193,48617]
D (5915,12795]
I (31242,41783)
结果:(31242,37894]
(2)
D (20548,58380]
I [29921,50343]
C (55622,56388)
U (10663,55963)
S (13419,44485]
U (312,17641)
C (22888,46679)
I (146,34564)
S [52222,58635]
U (48414,52854]
D [63519,64154]
I (56730,58078)
S (35200,62027)
U [56629,59581]
U (34709,53176)
C (47617,50554)
C [59810,59879)
U [30945,35759]
S (63271,64382)
U (34039,58443)
S [34619,36867]
U [56291,64980)
U (28366,51780)
C [18035,62732]
S [31184,48714)
D [34641,64321]
I (35962,41647)
U (24485,65483)
D (54664,57957)
I (52186,61938)
C (5202,41608)
I [9726,37424]
U [6217,39511)
C (60703,64624)
D [60815,63894]
I [59317,63281]
U [40880,58971]
结果:[40880,58971] (60703,60815)
(3)
D (51901,59602]
C (27695,51572)
I (29957,43634)
D [64513,64737)
D (55877,58852)
D [50724,65161)
I (41470,64906)
I [21977,42189)
C [54859,58026)
C [7445,33368)
C [45127,61859)
I [49461,62419]
D [43476,47025)
S [25627,60097]
I (50585,60476]
I (36008,39441)
D [44098,48937)
D (5174,56696]
D (12119,45532]
C [33201,50399]
C (603,29859]
D [19415,53914]
U (35233,51370]
U [45301,45736)
U [60777,62008)
U [25292,51148)
S (50351,64164]
I (28419,49526]
S (56837,59700]
I (34427,50635]
C (28818,46140)
C (34941,61670]
C (54625,60209)
U (54769,57335]
S [8177,30820)
D (14943,28934]
I (43462,62257)
结果:(54769,57335]