比较基础的矩形切割。
是POJ 2528 Mayor's posters的二维版。
还是要注意边缘的情况,比如当(0,8)(18,18) 切割(18,0)(19,19)的时候,结果应该是得到三个矩形
(18,19)(18,19) --> 面积为1
(19,0)(19,19) --> 面积为20
(18,0)(18,7) --> 面积为8
恩,其实我一直没搞懂为啥给数据的时候llx和lly是真正的坐标值,而urx和ury却必须减一之后再用...


1 /* 2 ID: xjtuacm1 3 PROG: rect1 4 LANG: C++ 5 */ 6 #include<iostream> 7 #include<stack> 8 #include<cstring> 9 #include<cstdio> 10 #include<queue> 11 #include<algorithm> 12 #include<set> 13 #include<map> 14 #include<vector> 15 #include<cmath> 16 using namespace std; 17 const int M = 100000; 18 const int N = 1000; 19 20 struct rect 21 { 22 int llx, lly; 23 int urx, ury; 24 int color; 25 rect(int lx = 0, int ly = 0, int rx = 0, int ry = 0, int c = 0) 26 : llx(lx), lly(ly), urx(rx), ury(ry), color(c) {} 27 28 int S() 29 { 30 return (urx - llx + 1) * (ury - lly + 1); 31 } 32 }rects[M], cur; 33 int tot; 34 35 inline bool cross(const rect& r1, const rect& r2) 36 { 37 return !( 38 (r1.llx > r2.urx) 39 || (r1.urx < r2.llx) 40 || (r1.lly > r2.ury) 41 || (r1.ury < r2.lly)); 42 43 } 44 45 inline void add(const rect& t) 46 { 47 rects[tot++] = t; 48 } 49 50 inline void del(int idx) 51 { 52 rects[idx] = rects[--tot]; 53 } 54 55 void cut(const rect& t, bool vertical = false) 56 { 57 int k1, k2; 58 rect tem = t; 59 if(vertical) 60 { 61 k1 = max(t.lly, cur.lly); 62 k2 = min(t.ury, cur.ury); 63 if(t.lly < k1) 64 { 65 tem.ury = k1 - 1; 66 add(tem); 67 } 68 if(k2 < t.ury) 69 { 70 tem = t, tem.lly = k2 + 1; 71 add(tem); 72 } 73 } 74 else 75 { 76 k1 = max(t.llx, cur.llx); 77 k2 = min(t.urx, cur.urx); 78 if(t.llx < k1) 79 { 80 tem.urx = k1 - 1; 81 add(tem); 82 } 83 if(t.urx > k2) 84 { 85 tem = t, tem.llx = k2 + 1; 86 add(tem); 87 } 88 tem = t, tem.llx = k1 , tem.urx = k2; 89 cut(tem, true); 90 } 91 } 92 93 94 int main(int argc, char *argv[]) 95 { 96 #ifdef ACM_LOCAL // Local 97 freopen("in", "r", stdin); 98 #else 99 #ifndef ONLINE_JUDGE // not HDOJ / POJ 100 freopen("rect1.in", "r", stdin); 101 freopen("rect1.out", "w", stdout); 102 #endif 103 #endif 104 105 int a, b, n; 106 scanf("%d %d %d", &a, &b, &n); 107 add(rect(0, 0, a-1, b-1, 1)); // add the white sheet first. 108 109 while(n--) 110 { 111 scanf("%d %d %d %d %d", &cur.llx, &cur.lly, &cur.urx, &cur.ury, &cur.color); 112 cur.urx--, cur.ury--; 113 114 for(int i = tot-1; i>= 0; i--) 115 { 116 if(cross(cur, rects[i])) 117 { 118 cut(rects[i]); 119 del(i); 120 } 121 } 122 add(cur); 123 } 124 125 map<int, int> cnt; 126 for(int i = 0; i!= tot; i++) 127 { 128 cnt[rects[i].color] += rects[i].S(); 129 } 130 131 for(map<int, int>::iterator it = cnt.begin(); it!= cnt.end(); it++) 132 { 133 if(it->second) 134 printf("%d %d\n", it->first, it->second); 135 } 136 137 return 0; 138 }
BTW, 果然学新的算法就要跟着代码一行一行调试~虽然感觉上慢了点但是可以掌握透彻~
还有,IOI国家集训队论文2004年薛茅的讲线段树跟矩形切割的,很清楚。在这里。