pku 3225 区间 我对线段树延迟标记的一些理解
这题网上结题报告应该很多了,我也不想多写什么,但是写完这题后,我对延迟标记的更新策略有了更新的理解
这题节点的结构应该算复杂的了
1
struct
tree
2 {
3 int s,e;
4 char cover,del,turn,sta;
5 }st[ 65540 * 8 ];
2 {
3 int s,e;
4 char cover,del,turn,sta;
5 }st[ 65540 * 8 ];
其中除了状态域,总共有3个延迟标记。合法的节点应该是至多存在一个延迟标记。所以我们在push_down的时候,当前节点至多有1个延迟标记,我们也要保证将该标记传递下去以后,儿子节点也要满足至多存在一个延迟的约束,否则我们将无法处理木有优先级的多个标志重叠的情况。例如这题:
1
void
push(
int
pos)
2 {
3 if (st[pos].turn)
4 {
5 st[pos].sta =! st[pos].sta;
6 st[pos].turn = 0 ;
7 if (st[pos].e != st[pos].s)
8 {
9 if (st[L].cover) st[L].cover = 0 ,st[L].del = 1 ;
10 else if (st[L].del) st[L].cover = 1 ,st[L].del = 0 ;
11 else st[L].turn =! st[L].turn;
12 if (st[R].cover) st[R].cover = 0 ,st[R].del = 1 ;
13 else if (st[R].del) st[R].cover = 1 ,st[R].del = 0 ;
14 else st[R].turn =! st[R].turn;
15 }
16 }
17 else if (st[pos].cover)
18 {
19 st[pos].cover = 0 ;
20 st[pos].sta = 1 ;
21 if (st[pos].e != st[pos].s)
22 {
23 st[L].cover = 1 ;
24 st[L].del = 0 ;
25 st[L].turn = 0 ;
26 st[R].cover = 1 ;
27 st[R].del = 0 ;
28 st[R].turn = 0 ;
29 }
30 }
31 else if (st[pos].del)
32 {
33 st[pos].del = 0 ;
34 st[pos].sta = 0 ;
35 if (st[pos].e != st[pos].s)
36 {
37 st[L].cover = 0 ;
38 st[L].turn = 0 ;
39 st[L].del = 1 ;
40 st[R].cover = 0 ;
41 st[R].del = 1 ;
42 st[R].turn = 0 ;
43 }
44 }
45 }
2 {
3 if (st[pos].turn)
4 {
5 st[pos].sta =! st[pos].sta;
6 st[pos].turn = 0 ;
7 if (st[pos].e != st[pos].s)
8 {
9 if (st[L].cover) st[L].cover = 0 ,st[L].del = 1 ;
10 else if (st[L].del) st[L].cover = 1 ,st[L].del = 0 ;
11 else st[L].turn =! st[L].turn;
12 if (st[R].cover) st[R].cover = 0 ,st[R].del = 1 ;
13 else if (st[R].del) st[R].cover = 1 ,st[R].del = 0 ;
14 else st[R].turn =! st[R].turn;
15 }
16 }
17 else if (st[pos].cover)
18 {
19 st[pos].cover = 0 ;
20 st[pos].sta = 1 ;
21 if (st[pos].e != st[pos].s)
22 {
23 st[L].cover = 1 ;
24 st[L].del = 0 ;
25 st[L].turn = 0 ;
26 st[R].cover = 1 ;
27 st[R].del = 0 ;
28 st[R].turn = 0 ;
29 }
30 }
31 else if (st[pos].del)
32 {
33 st[pos].del = 0 ;
34 st[pos].sta = 0 ;
35 if (st[pos].e != st[pos].s)
36 {
37 st[L].cover = 0 ;
38 st[L].turn = 0 ;
39 st[L].del = 1 ;
40 st[R].cover = 0 ;
41 st[R].del = 1 ;
42 st[R].turn = 0 ;
43 }
44 }
45 }
所有操作函数的结构都应该是这样的
1
void
insert(
int
s,
int
e,
int
pos)
2 {
3 push(pos);
4 if (st[pos].s == s && st[pos].e == e) st[pos].cover = 1 ;
5 else if (e <= M) insert(s,e,L);
6 else if (s >= M + 1 ) insert(s,e,R);
7 else insert(s,M,L),insert(M + 1 ,e,R);
8 }
2 {
3 push(pos);
4 if (st[pos].s == s && st[pos].e == e) st[pos].cover = 1 ;
5 else if (e <= M) insert(s,e,L);
6 else if (s >= M + 1 ) insert(s,e,R);
7 else insert(s,M,L),insert(M + 1 ,e,R);
8 }
因为这题木有向上维护的过程,如果有的话,末尾要加上
push(L),push(R),update(pos);
所有线段树的结构都是如此,更新策略也亦是如此,只要保证节点至多1个延迟标记 的性质,题目就不会错。
最后,附上本题得完整代码,感觉我写的算清楚的了
1
# include
<
stdio.h
>
2 # include < string .h >
3 # include < stdlib.h >
4 struct tree
5 {
6 int s,e;
7 char cover,del,turn,sta;
8 }st[ 65540 * 8 ];
9 # define M ((st[pos].s + st[pos].e) >> 1 )
10 # define L (pos << 1 )
11 # define R ((pos << 1 ) + 1 )
12 void init( int s, int e, int pos)
13 {
14 st[pos].s = s;
15 st[pos].e = e;
16 st[pos].cover = st[pos].del = st[pos].turn = st[pos].sta = 0 ;
17 if (e != s)
18 init(s,M,L),init(M + 1 ,e,R);
19 }
20 void push( int pos)
21 {
22 if (st[pos].turn)
23 {
24 st[pos].sta =! st[pos].sta;
25 st[pos].turn = 0 ;
26 if (st[pos].e != st[pos].s)
27 {
28 if (st[L].cover) st[L].cover = 0 ,st[L].del = 1 ;
29 else if (st[L].del) st[L].cover = 1 ,st[L].del = 0 ;
30 else st[L].turn =! st[L].turn;
31 if (st[R].cover) st[R].cover = 0 ,st[R].del = 1 ;
32 else if (st[R].del) st[R].cover = 1 ,st[R].del = 0 ;
33 else st[R].turn =! st[R].turn;
34 }
35 }
36 else if (st[pos].cover)
37 {
38 st[pos].cover = 0 ;
39 st[pos].sta = 1 ;
40 if (st[pos].e != st[pos].s)
41 {
42 st[L].cover = 1 ;
43 st[L].del = 0 ;
44 st[L].turn = 0 ;
45 st[R].cover = 1 ;
46 st[R].del = 0 ;
47 st[R].turn = 0 ;
48 }
49 }
50 else if (st[pos].del)
51 {
52 st[pos].del = 0 ;
53 st[pos].sta = 0 ;
54 if (st[pos].e != st[pos].s)
55 {
56 st[L].cover = 0 ;
57 st[L].turn = 0 ;
58 st[L].del = 1 ;
59 st[R].cover = 0 ;
60 st[R].del = 1 ;
61 st[R].turn = 0 ;
62 }
63 }
64 }
65 void insert( int s, int e, int pos)
66 {
67 push(pos);
68 if (st[pos].s == s && st[pos].e == e) st[pos].cover = 1 ;
69 else if (e <= M) insert(s,e,L);
70 else if (s >= M + 1 ) insert(s,e,R);
71 else insert(s,M,L),insert(M + 1 ,e,R);
72 }
73 void clear( int s, int e, int pos)
74 {
75 push(pos);
76 if (st[pos].s == s && st[pos].e == e) st[pos].del = 1 ;
77 else if (e <= M) clear(s,e,L);
78 else if (s >= M + 1 ) clear(s,e,R);
79 else clear(s,M,L),clear(M + 1 ,e,R);
80 }
81 void turn( int s, int e, int pos)
82 {
83 push(pos);
84 if (st[pos].s == s && st[pos].e == e) st[pos].turn =! st[pos].turn;
85 else if (e <= M) turn(s,e,L);
86 else if (s >= M + 1 ) turn(s,e,R);
87 else turn(s,M,L),turn(M + 1 ,e,R);
88 }
89 int quarry( int pos, int target)
90 {
91 push(pos);
92 if (st[pos].s == target && st[pos].e == target)
93 return st[pos].turn ?! st[pos].sta:st[pos].sta;
94 else if (target > M) return st[pos].turn ?! quarry(R,target):quarry(R,target);
95 else return st[pos].turn ?! quarry(L,target):quarry(L,target);
96 }
97 void print()
98 {
99 int i,last =- 1 ,used = 0 ;
100 for (i = 0 ;i <= 65540 * 2 ;i ++ )
101 {
102 if (quarry( 1 ,i))
103 {
104 if (last ==- 1 ) last = i;
105 used = 1 ;
106 }
107 else
108 {
109 if (last !=- 1 )
110 {
111 printf( " %c%d,%d%c " ,last % 2 ? ' ( ' : ' [ ' ,last / 2 ,(i - 1 ) % 2 ? (i - 1 ) / 2 + 1 :(i - 1 ) / 2 ,(i - 1 ) % 2 ? ' ) ' : ' ] ' );
112 last =- 1 ;
113 }
114 }
115 }
116 if ( ! used) printf( " empty set " );
117 printf( " \n " );
118 }
119 int main()
120 {
121
122 char jud[ 5 ];
123 init( 0 , 65540 * 2 , 1 );
124 while (scanf( " %s " ,jud) != EOF)
125 {
126 char str[ 128 ],type1,type2;
127 int num1,num2;
128 scanf( " %s " ,str);
129 type1 = ( * str == ' ( ' );
130 type2 = (str[strlen(str) - 1 ] == ' ) ' );
131 str[strlen(str) - 1 ] = ' \0 ' ;
132 num1 = atoi(strtok(str + 1 , " , " ));
133 num2 = atoi(strtok(NULL, " " ));
134 if (type1) num1 = num1 * 2 + 1 ;
135 else num1 = num1 * 2 ;
136 if (type2) num2 = num2 * 2 - 1 ;
137 else num2 = num2 * 2 ;
138 switch (jud[ 0 ])
139 {
140 case ' U ' :
141 if (num1 <= num2)
142 insert(num1,num2, 1 );
143 break ;
144 case ' I ' :
145 if (num1 <= num2)
146 {
147 if ( 0 <= num1 - 1 ) clear( 0 ,num1 - 1 , 1 );
148 if (num2 + 1 <= 65540 * 2 ) clear(num2 + 1 , 65540 * 2 , 1 );
149 }
150 else clear( 0 , 65540 * 2 , 1 );
151 break ;
152 case ' D ' :
153 if (num1 <= num2)
154 clear(num1,num2, 1 );
155 break ;
156 case ' C ' :
157 if (num1 <= num2)
158 {
159 if ( 0 <= num1 - 1 ) clear( 0 ,num1 - 1 , 1 );
160 if (num2 + 1 <= 65540 * 2 ) clear(num2 + 1 , 65540 * 2 , 1 );
161 turn(num1,num2, 1 );
162 }
163 else
164 clear( 0 , 65540 * 2 , 1 );
165 break ;
166 case ' S ' :
167 if (num1 <= num2)
168 turn(num1,num2, 1 );
169 break ;
170 }
171 }
172 print();
173 return 0 ;
174 }
2 # include < string .h >
3 # include < stdlib.h >
4 struct tree
5 {
6 int s,e;
7 char cover,del,turn,sta;
8 }st[ 65540 * 8 ];
9 # define M ((st[pos].s + st[pos].e) >> 1 )
10 # define L (pos << 1 )
11 # define R ((pos << 1 ) + 1 )
12 void init( int s, int e, int pos)
13 {
14 st[pos].s = s;
15 st[pos].e = e;
16 st[pos].cover = st[pos].del = st[pos].turn = st[pos].sta = 0 ;
17 if (e != s)
18 init(s,M,L),init(M + 1 ,e,R);
19 }
20 void push( int pos)
21 {
22 if (st[pos].turn)
23 {
24 st[pos].sta =! st[pos].sta;
25 st[pos].turn = 0 ;
26 if (st[pos].e != st[pos].s)
27 {
28 if (st[L].cover) st[L].cover = 0 ,st[L].del = 1 ;
29 else if (st[L].del) st[L].cover = 1 ,st[L].del = 0 ;
30 else st[L].turn =! st[L].turn;
31 if (st[R].cover) st[R].cover = 0 ,st[R].del = 1 ;
32 else if (st[R].del) st[R].cover = 1 ,st[R].del = 0 ;
33 else st[R].turn =! st[R].turn;
34 }
35 }
36 else if (st[pos].cover)
37 {
38 st[pos].cover = 0 ;
39 st[pos].sta = 1 ;
40 if (st[pos].e != st[pos].s)
41 {
42 st[L].cover = 1 ;
43 st[L].del = 0 ;
44 st[L].turn = 0 ;
45 st[R].cover = 1 ;
46 st[R].del = 0 ;
47 st[R].turn = 0 ;
48 }
49 }
50 else if (st[pos].del)
51 {
52 st[pos].del = 0 ;
53 st[pos].sta = 0 ;
54 if (st[pos].e != st[pos].s)
55 {
56 st[L].cover = 0 ;
57 st[L].turn = 0 ;
58 st[L].del = 1 ;
59 st[R].cover = 0 ;
60 st[R].del = 1 ;
61 st[R].turn = 0 ;
62 }
63 }
64 }
65 void insert( int s, int e, int pos)
66 {
67 push(pos);
68 if (st[pos].s == s && st[pos].e == e) st[pos].cover = 1 ;
69 else if (e <= M) insert(s,e,L);
70 else if (s >= M + 1 ) insert(s,e,R);
71 else insert(s,M,L),insert(M + 1 ,e,R);
72 }
73 void clear( int s, int e, int pos)
74 {
75 push(pos);
76 if (st[pos].s == s && st[pos].e == e) st[pos].del = 1 ;
77 else if (e <= M) clear(s,e,L);
78 else if (s >= M + 1 ) clear(s,e,R);
79 else clear(s,M,L),clear(M + 1 ,e,R);
80 }
81 void turn( int s, int e, int pos)
82 {
83 push(pos);
84 if (st[pos].s == s && st[pos].e == e) st[pos].turn =! st[pos].turn;
85 else if (e <= M) turn(s,e,L);
86 else if (s >= M + 1 ) turn(s,e,R);
87 else turn(s,M,L),turn(M + 1 ,e,R);
88 }
89 int quarry( int pos, int target)
90 {
91 push(pos);
92 if (st[pos].s == target && st[pos].e == target)
93 return st[pos].turn ?! st[pos].sta:st[pos].sta;
94 else if (target > M) return st[pos].turn ?! quarry(R,target):quarry(R,target);
95 else return st[pos].turn ?! quarry(L,target):quarry(L,target);
96 }
97 void print()
98 {
99 int i,last =- 1 ,used = 0 ;
100 for (i = 0 ;i <= 65540 * 2 ;i ++ )
101 {
102 if (quarry( 1 ,i))
103 {
104 if (last ==- 1 ) last = i;
105 used = 1 ;
106 }
107 else
108 {
109 if (last !=- 1 )
110 {
111 printf( " %c%d,%d%c " ,last % 2 ? ' ( ' : ' [ ' ,last / 2 ,(i - 1 ) % 2 ? (i - 1 ) / 2 + 1 :(i - 1 ) / 2 ,(i - 1 ) % 2 ? ' ) ' : ' ] ' );
112 last =- 1 ;
113 }
114 }
115 }
116 if ( ! used) printf( " empty set " );
117 printf( " \n " );
118 }
119 int main()
120 {
121
122 char jud[ 5 ];
123 init( 0 , 65540 * 2 , 1 );
124 while (scanf( " %s " ,jud) != EOF)
125 {
126 char str[ 128 ],type1,type2;
127 int num1,num2;
128 scanf( " %s " ,str);
129 type1 = ( * str == ' ( ' );
130 type2 = (str[strlen(str) - 1 ] == ' ) ' );
131 str[strlen(str) - 1 ] = ' \0 ' ;
132 num1 = atoi(strtok(str + 1 , " , " ));
133 num2 = atoi(strtok(NULL, " " ));
134 if (type1) num1 = num1 * 2 + 1 ;
135 else num1 = num1 * 2 ;
136 if (type2) num2 = num2 * 2 - 1 ;
137 else num2 = num2 * 2 ;
138 switch (jud[ 0 ])
139 {
140 case ' U ' :
141 if (num1 <= num2)
142 insert(num1,num2, 1 );
143 break ;
144 case ' I ' :
145 if (num1 <= num2)
146 {
147 if ( 0 <= num1 - 1 ) clear( 0 ,num1 - 1 , 1 );
148 if (num2 + 1 <= 65540 * 2 ) clear(num2 + 1 , 65540 * 2 , 1 );
149 }
150 else clear( 0 , 65540 * 2 , 1 );
151 break ;
152 case ' D ' :
153 if (num1 <= num2)
154 clear(num1,num2, 1 );
155 break ;
156 case ' C ' :
157 if (num1 <= num2)
158 {
159 if ( 0 <= num1 - 1 ) clear( 0 ,num1 - 1 , 1 );
160 if (num2 + 1 <= 65540 * 2 ) clear(num2 + 1 , 65540 * 2 , 1 );
161 turn(num1,num2, 1 );
162 }
163 else
164 clear( 0 , 65540 * 2 , 1 );
165 break ;
166 case ' S ' :
167 if (num1 <= num2)
168 turn(num1,num2, 1 );
169 break ;
170 }
171 }
172 print();
173 return 0 ;
174 }