HDU3265 掃描線+線段樹 區間並
阿新 • • 發佈:2019-01-23
題意:N個海報,每個海報中間有個矩形的洞。問這N個海報覆蓋面積和是多少。
分析: 非常經典的題目了,掃描線+線段樹 進行 區間並操作
既然海報內有塊矩形不能計算入內,只要把海報分為四塊不重疊的部分就好了。
重點是空間限制比較緊,交了若干次才A的。。改用unsigned short(0...65536) 儲存座標才A了。。
注意:若掃描線個數小於2直接輸出0,如果按常規的線段樹求區間和會返回RE。。
截圖紀念一下這個讓我除錯了N久bug的題目。。
程式碼如下:
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 4e5+10; struct Line{ unsigned short x,y1,y2; bool f; bool operator <(const Line &rhs) const { return x<rhs.x; } }line[maxn]; int y[maxn]; int n,tot; inline void addLine(int a, int b,int c, int d) { tot++; line[tot].x = a; line[tot].y1 = b; line[tot].y2 = d; line[tot].f = 1; y[tot] = b; tot++; line[tot].x = c; line[tot].y1 = b; line[tot].y2 = d; line[tot].f = 0; y[tot] = d; } struct node{ int l,r; int c,len; int lf,rf; }; struct Tree{ node tr[maxn*4]; #define lch(u) (u<<1) #define rch(u) (u<<1|1) #define Mid (tr[u].l+tr[u].r)>>1 void build(int u, int a, int b) { tr[u].l = a; tr[u].r = b; tr[u].lf = y[a]; tr[u].rf = y[b]; tr[u].c = tr[u].len = 0; if (a+1 == b) return ; build(lch(u),a,Mid); build(rch(u),Mid,b); } inline void cal(int u){ if (tr[u].c > 0) { tr[u].len = tr[u].rf - tr[u].lf; } else { if (tr[u].l+1 == tr[u].r) tr[u].len = 0; else tr[u].len = tr[lch(u)].len + tr[rch(u)].len; } } void update(int u, Line e){ if (e.y1 == tr[u].lf && e.y2 == tr[u].rf) { if (e.f == 1) tr[u].c++; else tr[u].c--; cal(u); return ; } if (e.y2 <= tr[lch(u)].rf) update(lch(u),e); else if (e.y1 >= tr[rch(u)].lf) update(rch(u),e); else { Line tmp = e; tmp.y2 = tr[lch(u)].rf; update(lch(u),tmp); tmp = e; tmp.y1 = tr[rch(u)].lf; update(rch(u),tmp); } cal(u); } }T; int x[10]; int main(){ while (scanf("%d",&n)==1 && n){ tot = 0; for (int i=1; i<=n; i++) { for (int j=1; j<=8; j++) scanf("%d",&x[j]); if (x[1]<x[5] && x[2]<x[4]) addLine(x[1],x[2],x[5],x[4]); if (x[7]<x[3] && x[2]<x[4]) addLine(x[7],x[2],x[3],x[4]); if (x[5]<x[7] && x[8]<x[4]) addLine(x[5],x[8],x[7],x[4]); if (x[5]<x[7] && x[2]<x[6]) addLine(x[5],x[2],x[7],x[6]); } sort(line+1,line+tot+1); sort(y+1,y+tot+1); if (tot<2) { printf("0\n"); continue; } T.build(1,1,tot); T.update(1,line[1]); unsigned int ans = 0; for (int i=2; i<=tot; i++) { ans += T.tr[1].len*(line[i].x-line[i-1].x); T.update(1,line[i]); } printf("%u\n",ans); } return 0; }