宏大的区间

【问题描述】
小洪喜欢区间,他有一个宏大的区间游戏。
小洪有一个集合S(初始为空),然后,小洪会依次对这个区间做一些操作,操作分为5种,5种操作以及集合之间的运算规则如下:
 
 
wangy是小洪的粉丝,他想知道经过这些操作后的最终集合S。但他实在是太弱了,于是他找到了你,请你帮他解决这个问题。
 
【输入格式】
输入共m行,每行描述一个操作。
每行的格式为O T,用一个空格隔开。O表示运算的种类,T为一个区间。区间用(a,b), (a,b], [a,b), [a,b]表示。
保证输入数据中没有多余的空格。
 
【输出格式】
输出一行若干个用空格分开的区间,描述最终的集合S。你需要保证你输出的所有区间交集为空,并集为最终的S,并且你需要将它们按左端点从小到大排序。
特别地,如果最终的集合S为空集,则输出一行”empty set”(不含引号)。
 
【输入输出样例】
interval1.in
interval1.out
U [1,5]
D [3,3]
S [2,4]
C (1,5)
I (2,3]
U [4,6)
 
(2,3) [4,6)
interval2.in
interval2.out
S [3,5]
S [3,5]
 
empty set
 
【数据规模】
测试点编号
m
a,b
备注
1-3
n≤100
a,b≤255
 
4-6
所有区间为闭区间
7-8
n≤10001
a,b≤65535
9-12
n≤40000
13-15
n≤10001
 
16-19
n≤40000
 
20-25
n≤200000
a,b≤262143
 
对于所有的数据,保证m>0,0≤a≤b。保证输入数据中的所有区间均不为空。
 
考虑维护一棵权值线段树,中括号和小括号不好处理。
我们将值域*2,那么小括号对应奇数,中括号对应偶数。
线段树要支持区间赋值和区间取反的操作,注意空格输出空格。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define lim 524287
 4 #define M 1500010
 5 int q[M];
 6 inline void Do(int o) {
 7     if(q[o] == 1 || q[o] == -1) {
 8         q[2 * o] = q[2 * o + 1] = q[o];
 9     }
10     if(q[o] == 2) {
11         q[2 * o] = -q[2 * o];
12         q[2 * o + 1] = -q[2 * o + 1];
13     }
14     q[o] = -2;
15 }
16 inline void Add(int l, int r, int o, int x, int y, int z) {
17     if(x <= l && r <= y) {
18         q[o] = z;
19         return;
20     }
21     int mid = (l + r) / 2;
22     Do(o);
23     if(x <= mid) Add(l, mid, 2 * o, x, y, z);
24     if(y > mid) Add(mid + 1, r, 2 * o + 1, x, y, z);
25 }
26 inline void rev(int l, int r, int o, int x, int y) {
27     if(x <= l && r <= y) {
28         q[o] = -q[o];
29         return;
30     }
31     int mid = (l + r) / 2;
32     Do(o);
33     if(x <= mid) rev(l, mid, 2 * o, x, y);
34     if(y > mid) rev(mid + 1, r, 2 * o + 1, x, y);
35 }
36 inline void pd(int l, int r, int o) {
37     if(l == r) return;
38     int mid = (l + r) / 2;
39     Do(o);
40     pd(l, mid, 2 * o);
41     pd(mid + 1, r, 2 * o + 1);
42 }
43 int main() {
44     char s[10];
45     memset(q, -1, sizeof(q));
46     while(scanf("%s", s) != EOF) {
47         char A, B;
48         int l, r;
49         A = getchar();
50         while(A != '(' && A != '[') A = getchar();
51         scanf("%d,%d", &l, &r);
52         B = getchar();
53         while(B != ')' && B != ']') B = getchar();
54         l = l * 2 + (A == '(');
55         r = r * 2 - (B == ')');
56         if(s[0] == 'U') {
57             Add(0, lim, 1, l, r, 1);
58         }
59         else if(s[0] == 'I') {
60             if(l) Add(0, lim, 1, 0, l - 1, -1);
61             Add(0, lim, 1, r + 1, lim, -1);
62         }
63         else if(s[0] == 'D') {
64             Add(0, lim, 1, l, r, -1);
65         }
66         else if(s[0] == 'C') {
67             if(l) Add(0, lim, 1, 0, l - 1, -1);
68             Add(0, lim, 1, r + 1, lim, -1);
69             rev(0, lim, 1, l, r);
70         }
71         else {
72             rev(0, lim, 1, l, r);
73         }
74     }
75     pd(0, lim, 1);
76     q[lim] = -1;
77     bool flag = false;
78     for(int i = 0; i <= lim; ++ i) {
79         if(q[lim + i] == -1 && q[i + lim + 1] == 1) {
80             if(flag) printf(" ");
81             if(i & 1) printf("(");
82             else printf("[");
83             printf("%d,", i / 2);
84             flag = true;
85         }
86         if(q[lim + i] == 1 && q[i + lim + 1] == -1) {
87             printf("%d", i / 2);
88             if(i & 1) printf("]");
89             else printf(")");
90         }
91     }
92     if(!flag) puts("empty set");
93 }
原文地址:https://www.cnblogs.com/iamqzh233/p/9458136.html