Adieu l'ami.
Koyomi is helping Oshino, an acquaintance of his, to take care of an open space around the abandoned Eikou Cram School building, Oshino's makeshift residence.
The space is represented by a rectangular grid of n × m cells, arranged into n rows and m columns. The c-th cell in the r-th row is denoted by (r, c).
Oshino places and removes barriers around rectangular areas of cells. Specifically, an action denoted by "1 r1 c1 r2 c2" means Oshino's placing barriers around a rectangle with two corners being (r1, c1) and (r2, c2) and sides parallel to squares sides. Similarly, "2 r1 c1 r2 c2" means Oshino's removing barriers around the rectangle. Oshino ensures that no barriers staying on the ground share any common points, nor do they intersect with boundaries of the n × m area.
Sometimes Koyomi tries to walk from one cell to another carefully without striding over barriers, in order to avoid damaging various items on the ground. "3 r1 c1 r2 c2" means that Koyomi tries to walk from (r1, c1) to (r2, c2) without crossing barriers.
And you're here to tell Koyomi the feasibility of each of his attempts.
The first line of input contains three space-separated integers n, m and q (1 ≤ n, m ≤ 2 500, 1 ≤ q ≤ 100 000) — the number of rows and columns in the grid, and the total number of Oshino and Koyomi's actions, respectively.
The following q lines each describes an action, containing five space-separated integers t, r1, c1, r2, c2 (1 ≤ t ≤ 3, 1 ≤ r1, r2 ≤ n, 1 ≤ c1, c2 ≤ m) — the type and two coordinates of an action. Additionally, the following holds depending on the value of t:
- If t = 1: 2 ≤ r1 ≤ r2 ≤ n - 1, 2 ≤ c1 ≤ c2 ≤ m - 1;
- If t = 2: 2 ≤ r1 ≤ r2 ≤ n - 1, 2 ≤ c1 ≤ c2 ≤ m - 1, the specified group of barriers exist on the ground before the removal.
- If t = 3: no extra restrictions.
For each of Koyomi's attempts (actions with t = 3), output one line — containing "Yes" (without quotes) if it's feasible, and "No" (without quotes) otherwise.
5 6 5
1 2 2 4 5
1 3 3 3 3
3 4 4 1 1
2 2 2 4 5
3 1 1 4 4
No
Yes
2500 2500 8
1 549 1279 1263 2189
1 303 795 1888 2432
1 2227 622 2418 1161
3 771 2492 1335 1433
1 2017 2100 2408 2160
3 48 60 798 729
1 347 708 1868 792
3 1940 2080 377 1546
No
Yes
No
For the first example, the situations of Koyomi's actions are illustrated below.
题目大意 在一个m×n的方格板上,操作1将一个矩形区域的边界上加上一圈障碍,操作2将一个矩形区域的边界上的障碍移除,操作3询问两点是否能不越过障碍互相到达。题目保证任意两圈矩形障碍不会有公共点(边界上)。
题目可以看成每次从平面中分割出一个小平面或者将一个平面复原,然后询问两个点是否在同一平面内。
于是常用套路打标记。
Solution 1 暴力差分
每次修改操作暴力每行进行差分。
当然这个差分得稍微改一下,前者用一个独一无二的正数,后者用一个负数。
查询的时候进行由那一行首往后扫描,如果遇到正数就压入栈,遇到负数就弹处栈顶。
最终栈顶就是这个点所在平面的标号。由于开始是在最外面的平面,所以首先在栈中加入一个元素。
然后判断一下两个点是否在同一平面就行了。
如果代码比较丑,请卡常数。
(最坏的时间复杂度是O(nq),虽然觉得不可思议,但它就是过了。。)
Code
1 /** 2 * Codeforces 3 * Problem#869E 4 * Accepted 5 * Time: 1934ms 6 * Memory: 24600k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 11 int n, m, q; 12 int top = 0; 13 int sta[2505]; 14 int mp[2505][2505]; 15 16 inline void init() { 17 scanf("%d%d%d", &n, &m, &q); 18 } 19 20 int getSign(int x, int y) { 21 top = 0; 22 sta[0] = 233333; 23 for(int i = 1; i <= y; i++) { 24 if(mp[x][i] > 0) 25 sta[++top] = mp[x][i]; 26 else if(mp[x][i] < 0) 27 top--; 28 } 29 return sta[top]; 30 } 31 32 inline void solve() { 33 int opt, x1, y1, x2, y2; 34 while(q--) { 35 scanf("%d%d%d%d%d", &opt, &x1, &y1, &x2, &y2); 36 switch(opt) { 37 case 1: 38 for(int i = x1; i <= x2; i++) 39 mp[i][y1] = q, mp[i][y2 + 1] = -1; 40 break; 41 case 2: 42 for(int i = x1; i <= x2; i++) 43 mp[i][y1] = 0, mp[i][y2 + 1] = 0; 44 break; 45 case 3: 46 top = 0; 47 puts((getSign(x1, y1) == getSign(x2, y2)) ? ("Yes") : ("No")); 48 break; 49 } 50 } 51 } 52 53 int main() { 54 init(); 55 solve(); 56 return 0; 57 }