题意:完成5种集合操作,输出最终的集合。
若把集合S
用0\1序列来表示,则集合操作可转化为对连续子序列(区间)的操作。
\(T^C\)表示\(T\)的补集
\(S \cup T\) | \(T\)区间置1 |
\(S \cap T\) | \(T^C\)区间置0 |
\(S - T\) | \(T\)区间置0 |
\(T - S\) | \(S\)取反,\(T^C\)区间置0 |
\(S \oplus T\) | \(T\)区间取反 |
区间操作有两种,置0\1和取反。置0\1可以用线段树打lazy tag来实现,取反也可以用打标记来实现。这里只用了一个标记,标记的种类有无标记、0、1、取反四种,打0\1标记时不需要考虑之前标记的类型,打取反标记时,若之前为0\1,则标记变为1\0,若之前为取反,则变为无标记,若之前为无标记,则变为取反标记。
最后,在完成所有操作后,下传所有标记。
开区间、闭区间的处理:把集合序列扩充为原来的3倍,对于数a:
\(3a\) | ) |
\(3a+1\) | ] or[ |
\(3a+2\) | ( |
这样,(a,b)
包含在[a,b]
中,集合取补操作也比较直观。
这篇博客对开闭区间的处理为扩充序列为原来的2倍,对于数a:
\(2a-1\) | ) |
\(2a\) | ] or[ |
\(2a+1\) | ( |
\(2a-1\)既表示a)
,也表示(a-1
。
坑:第一次见用开闭区间表示实数集合,开始还以为区间表示的是整数集合,看着样例输出(2,3)
一脸懵…
1 |
|