求矩形的并 Poj1151
线段树,离散化,扫描线。
1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <cstring> 11 #include <map> 12 #include <stack> 13 #include <set> 14 #define LL long long 15 #define INF 0x3f3f3f3f 16 #define OPEN_FILE 17 using namespace std; 18 const int MAXN = 5005; 19 struct Line{ 20 double left, right; 21 double y; 22 int cnt; 23 Line(){}; 24 Line(double left, double right, double y, int cnt) :left(left), right(right), y(y), cnt(cnt){}; 25 }; 26 bool operator < (Line a, Line b){ 27 return a.y < b.y; 28 } 29 struct Node{ 30 double left, right; 31 int from, to; 32 int cnt; 33 double value; 34 }; 35 int n; 36 double a[MAXN]; 37 Line scan[MAXN]; 38 Node f[MAXN << 1]; 39 void build(int t, int left, int right){ 40 f[t].left = a[left]; 41 f[t].right = a[right]; 42 f[t].from = left; 43 f[t].to = right; 44 f[t].cnt = f[t].value = 0; 45 if (right - left == 1) return; 46 int mid = (left + right) >> 1; 47 build(t << 1, left, mid); 48 build((t << 1) + 1, mid, right); 49 } 50 void update(int t, Line p){ 51 if (p.left == f[t].left && p.right == f[t].right){ 52 f[t].cnt += p.cnt; 53 if (f[t].cnt > 0){ 54 f[t].value = p.right - p.left; 55 return; 56 } 57 if (f[t].to - f[t].from == 1){ 58 f[t].value = 0; 59 } 60 else{ 61 f[t].value = f[t << 1].value + f[(t << 1) + 1].value; 62 } 63 return; 64 } 65 if (p.left >= f[(t << 1) + 1].left){ 66 update((t << 1) + 1, p); 67 } 68 else if (p.right <= f[t << 1].right){ 69 update(t << 1, p); 70 } 71 else{ 72 Line q = p; 73 q.right = f[t << 1].right; 74 update(t << 1, q); 75 q = p; 76 q.left = f[(t << 1) + 1].left; 77 update((t << 1) + 1, q); 78 } 79 if (f[t].cnt > 0){ 80 f[t].value = f[t].right - f[t].left; 81 } 82 else{ 83 f[t].value = f[t].to - f[t].from == 1 ?0:f[t << 1].value + f[(t << 1) + 1].value; 84 } 85 } 86 int main() 87 { 88 #ifdef OPEN_FILE 89 //freopen("in.txt", "r", stdin); 90 //freopen("out.txt", "w", stdout); 91 #endif // OPEN_FILE 92 double x1, y1, x2, y2; 93 int cas = 1; 94 while (~scanf("%d", &n) && n != 0){ 95 for (int i = 1; i <= n; i++){ 96 scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); 97 a[i * 2 - 1] = x1; 98 a[i * 2] = x2; 99 scan[i * 2 - 1] = Line(x1, x2, y1, 1); 100 scan[i * 2] = Line(x1, x2, y2, -1); 101 } 102 n = n * 2; 103 double ans = 0.0; 104 memset(f, 0, sizeof(f)); 105 sort(a + 1, a + n + 1); 106 sort(scan + 1, scan + n + 1); 107 build(1, 1, n); 108 update(1, scan[1]); 109 for (int i = 2; i <= n; i++){ 110 ans += f[1].value * (scan[i].y - scan[i - 1].y); 111 update(1, scan[i]); 112 } 113 printf("Test case #%d\nTotal explored area: %.2lf\n\n", cas++, ans); 114 } 115 }
并查集应用 poj1182
以前对并查集的印象还停留在高中,只是记录一下是不是已经连通。这里加了一个数组rank[i]表示i的秩,也就是到祖先的距离,其实都是高中的内容。
//set void MakeSet(int x){ father[x] = x; rank[x] = 0; } //find int FindSet(int x) { if (x != father[x]) { father[x] = FindSet(father[x]); } return father[x]; } //union void Union(int x, int y) { x = FindSet(x); y = FindSet(y); if (x == y) return; if (rank[x] > rank[y]) { father[y] = x; rank[x] += rank[y]; } else { if (rank[x] == rank[y]) { rank[y]++; } father[x] = y; } }