[PKU 3225] 线段树应用

{

线段树应用

就是那些可以用线段树做

但是不是简单地套模版可以解决的问题

应用两字可谓深不见底

}

 

原题

  http://poj.org/problem?id=3225

 

题意

  给定初始的实数空集S

  和多个集合操作{C T}(交 并 差)

  要求输出操作完最后的集合S

  比较特别的是 给定的T集合都是区间形式

 

这是一个典型的数据结构问题

还是要求我们设计一个程序来支持多个操作

我们的设想是 使用较少的函数 经过适当的组合 支持更多的操作

这个问题要支持5种操作 我们可以逐个分析 统一处理

——这也是此类数据结构问题的解决方法之一

 

我们对5种操作逐个分析

对于求交操作

我们注意到 一个元素只需在其中任意一个中出现就会被取得

这就相当于逻辑或操作 所以我们不妨把实数集合转化为布尔集合

每一个布尔变量代表相应的实数取或不取 相应的 T集合就是一个全为真的集合

由于T是一个区间 分类讨论在T范围内河不在T范围内的情况

对于在T范围内的时候 由于T全为真 所以T范围内的数全被取得

而不在T范围内时 如果元素在S内就取得 不在就不取 保持原貌不动即可

对于求并操作

一个元素仅当在2个集合中都出现的时候才会被取得

相当于逻辑与操作 同样分T集合范围内外讨论

如果在T集合内 保持原貌不动 T集合之外 由于不属于T 全部不取

然后是求差 求差分3种 正差 反差 对称差

对于正差 S-T

即求取所有在S中且不在T中的元素

继续分情况讨论

对于T的范围内的元素 应当全部不取

对于T范围外的元素保持原貌即可

对于反差 T-S

即求取所有在T中且不在S中的元素

对于在T范围内的元素 如果在S中就不取 不在S中就取

就是对这一段S集合作取反操作

而对区T范围外的元素 全部不取

最后是对称差 (T-S)U(S-T)

其含义就是仅取在2个集合中只出现一次的元素

对于在T范围内的元素 对之一段S集合取反

对于T范围外的元素 保持不动

 

讨论完了以上者几中情况

我们发现5种操作本质上可以用2个函数组合完成

就是对S集合的某一段(T所包括的一段,T之外的两段) 全部取/不取全部取反

反映在布尔值上就是 全部取真/取假 和 取反

这样就划归成了我们熟悉的区间操作问题 利用线段树可以很好的解决

(善于自虐的同学可以写Splay)

还要使用2个常用的技巧 Lazy思想离散化

不细说了 本文重在应用二字 实现时需要注意以下几点

  离散化时把元线段端点和元线段内部等价离散

  即把数轴按整点整点之间的部分离散成相应的数

  

  这样端点取不取也可以解决了

  lazy标记需要2个 记录覆盖信息取反信息

  修改区间时直接修改标记 访问区间时更新并下传标记

  注意取反时优先考虑直接修改覆盖信息 覆盖时清除取反信息


给出我的代码

 

1 {$I+,Q+,R+,S+}
2  const max=200000;
3 size=max shl 1;
4  var l,r,ls,rs,bm,cm:array[1..size shl 1]of longint;
5 dm:array[1..size shl 1]of boolean;
6 ansx,ansy:array[1..size]of longint;
7 lch,rch,a,b,tt,lastx,lasty,i,code:longint;
8 c,ch,temp:char;
9 s:string;
10  procedure build(a,b:longint);
11  var x,mid:longint;
12  begin
13 inc(tt); x:=tt;
14 l[x]:=a; r[x]:=b;
15 cm[x]:=0; bm[x]:=-1; dm[x]:=false;
16  if b-a>1
17 then begin
18 mid:=(a+b)shr 1;
19 ls[x]:=tt+1; build(a,mid);
20 rs[x]:=tt+1; build(mid,b);
21 end;
22  end;
23  procedure down(x:longint);
24  begin
25  if bm[x]<>-1
26 then begin
27 cm[x]:=bm[x];
28 if ls[x]<>0
29 then begin
30 bm[ls[x]]:=bm[x];
31 dm[ls[x]]:=false;
32 end;
33 if rs[x]<>0
34 then begin
35 bm[rs[x]]:=bm[x];
36 dm[rs[x]]:=false;
37 end;
38 bm[x]:=-1;
39 end
40 else if dm[x]
41 then begin
42 if cm[x]<>2 then cm[x]:=1-cm[x];
43 if ls[x]<>0
44 then if bm[ls[x]]=-1
45 then dm[ls[x]]:=not dm[ls[x]]
46 else bm[ls[x]]:=1-bm[ls[x]];
47 if (ls[x]<>0)
48 then if bm[rs[x]]=-1
49 then dm[rs[x]]:=not dm[rs[x]]
50 else bm[rs[x]]:=1-bm[rs[x]];
51 dm[x]:=false;
52 end;
53 end;
54 procedure cover(x,a,b,c:longint);
55 var mid:longint;
56 begin
57 down(x);
58 if cm[x]=c then exit;
59 if (a<=l[x])and(r[x]<=b)
60 then begin
61 bm[x]:=c;
62 dm[x]:=false;
63 end
64 else begin
65 cm[x]:=2;
66 mid:=(l[x]+r[x])shr 1;
67 if a<mid then cover(ls[x],a,b,c);
68 if b>mid then cover(rs[x],a,b,c);
69 end;
70 end;
71 procedure change(x,a,b:longint);
72 var mid:longint;
73 begin
74 if x=12
75 then x:=x;
76 down(x);
77 if (a<=l[x])and(r[x]<=b)
78 then if bm[x]<>-1
79 then bm[x]:=1-bm[x]
80 else dm[x]:=not dm[x]
81 else begin
82 cm[x]:=2;
83 mid:=(l[x]+r[x])shr 1;
84 if a<mid then change(ls[x],a,b);
85 if b>mid then change(rs[x],a,b);
86 end;
87 end;
88 procedure calculate(x:longint);
89 var mid:longint;
90 begin
91 down(x);
92 if cm[x]=1
93 then begin
94 if lasty<>l[x]
95 then begin
96 inc(tt);
97 ansx[tt]:=lastx;
98 ansy[tt]:=lasty-1;
99 lastx:=l[x];
100 end;
101 lasty:=r[x];
102 end
103 else begin
104 if ls[x]<>0 then calculate(ls[x]);
105 if rs[x]<>0 then calculate(rs[x]);
106 end;
107 end;
108 begin
109 assign(input,'sets.in'); reset(input);
110 assign(output,'sets.out'); rewrite(output);
111 build(0,max);
112 while not eof do
113 begin
114 read(c);
115 read(temp);
116 read(temp);
117 s:='';
118 read(ch);
119 while ch<>',' do
120 begin
121 s:=s+ch;
122 read(ch);
123 end;
124 val(s,a,code); a:=a*2;
125 if temp='(' then a:=a+1;
126 read(ch); s:='';
127 while (ch<>')')and(ch<>']') do
128 begin
129 s:=s+ch;
130 read(ch);
131 end;
132 val(s,b,code); b:=b*2;
133 if ch=')' then b:=b-1;
134 readln;
135 case c of
136 'U': cover(1,a,b+1,1);
137 'I': begin
138 cover(1,0,a,0);
139 cover(1,b+1,max,0);
140 end;
141 'D': cover(1,a,b+1,0);
142 'C': begin
143 cover(1,0,a,0);
144 change(1,a,b+1);
145 cover(1,b+1,max,0);
146 end;
147 'S': change(1,a,b+1);
148 end;
149 end;
150 lastx:=-100; lasty:=-100;
151 tt:=0;
152 calculate(1);
153 inc(tt);
154 ansx[tt]:=lastx;
155 ansy[tt]:=lasty-1;
156 if tt=1
157 then write('empty set')
158 else for i:=2 to tt do
159 begin
160 if ansx[i] and 1=1
161 then write('(') else write('[');
162 write(ansx[i] shr 1,',',(ansy[i]+1) shr 1);
163 if ansy[i] and 1=1
164 then write(')') else write(']');
165 if i<>tt then write(' ');
166 end;
167 writeln;
168 close(input); close(output);
169 end.
170

 

 

应用使理论更完善!

 

Bob Han原创 转载请注明出处 http://www.cnblogs.com/Booble/

posted on 2010-10-02 22:09  Master_Chivu  阅读(2009)  评论(0编辑  收藏  举报

导航