1. 程式人生 > >Picture POJ - 1177(掃描線 + 線段樹)

Picture POJ - 1177(掃描線 + 線段樹)

區間 cstring pan double pen pic set sstream div

題意:求矩形並的面積。。

解析:

  掃描線第一道題。。。。自下而上掃描的。。。

如果不懂什麽是掃描線 戳我

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include 
<cmath> #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_wity_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 201, INF = 0x7fffffff; double
X[maxn]; //記錄x的坐標 struct node{ int l, r; // 線段樹的左右端點 int w; // 記錄邊重疊的情況 double lx, rx, sum; //sum代表當前區間線段的長度,lx和rx為線段的真實端點 }Node[maxn*4]; struct edge{ double lxx, rxx, y; // 存儲邊的左右端點和y int f; //標記是下邊還是上邊 (下邊為-1 上邊為1) }Edge[maxn]; int cmp(edge a, edge b) { return a.y < b.y; //
按y從小到大排序 把線段的高度從低到高排序 } void build(int k, int ll, int rr) //建樹 { Node[k].l = ll, Node[k].r = rr; Node[k].sum = Node[k].w = 0; Node[k].lx = X[ll]; Node[k].rx = X[rr]; if(ll + 1 == rr) return; int m = (ll + rr) / 2; build(k*2, ll, m); build(k*2+1, m, rr); } void down(int k) //計算長度 { if(Node[k].w > 0) { Node[k].sum = Node[k].rx - Node[k].lx; return; } if(Node[k].l + 1 == Node[k].r) Node[k].sum = 0; else { Node[k].sum = Node[k*2].sum + Node[k*2+1].sum; } } void update(int k, edge e) // 更新 { if(Node[k].lx == e.lxx && Node[k].rx == e.rxx) { Node[k].w += e.f; down(k); return; } if(e.rxx <= Node[k*2].rx) update(k*2, e); else if(e.lxx >= Node[k*2+1].lx) update(k*2+1, e); else { edge g = e; g.rxx = Node[k*2].rx; update(k*2, g); g = e; g.lxx = Node[k*2+1].lx; update(k*2+1, g); } down(k); } int main() { int n, cnt, kase = 0; while(~scanf("%d",&n) && n) { cnt = 0; for(int i=0; i<n; i++) { double x1, y1, x2, y2; scanf("%lf%lf%lf%lf",&x1, &y1, &x2, &y2); Edge[++cnt].lxx = x1, Edge[cnt].rxx = x2, Edge[cnt].y = y1, Edge[cnt].f = 1; X[cnt] = x1; Edge[++cnt].lxx = x1, Edge[cnt].rxx = x2, Edge[cnt].y = y2, Edge[cnt].f = -1; X[cnt] = x2; } sort(Edge+1, Edge+cnt+1, cmp); sort(X+1, X+cnt+1); build(1, 1, cnt); double ret = 0; for(int i=1; i<cnt; i++) { update(1, Edge[i]); ret += (Edge[i+1].y - Edge[i].y) * Node[1].sum; } printf("Test case #%d\nTotal explored area: %.2f\n\n",++kase,ret); } return 0; }

Picture POJ - 1177(掃描線 + 線段樹)