题意:有n(1<=n<=60000)个矩形散落在大矩形中,保证任意两个矩形没有一个交点,问每块被围出来的小面积的大小是多少。
题解:矩形并=线段树,对于这个题,由于任意两个矩形没有一个交点,着眼于lazy的性质,如果一个矩形能被另一个矩形包围起来,那么当前矩形的lazy一定
比另一个lazy小,遇到矩形的右边的时候再把lazy还原成father,这样搞出来一棵树,然后dfs即可。
Sure原创,转载请注明出处
#include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> #define ABS(x) ((x) >= 0 ? (x) : (-(x))) using namespace std; const int inf = 1 << 29; const int maxn = 60010; struct line { int x,down,up,id; bool operator < (const line &other) const { return x < other.x; } }vertical_line[maxn << 1]; struct node { int l,r; int lazy; }seg[maxn << 3]; struct nnode { int v; int next; }edge[maxn << 1]; int yy[maxn << 1],head[maxn],father[maxn]; __int64 area[maxn]; int w,h,n,tot,top,idx; void swap(int &a,int &b) { int tmp = a; a = b; b = tmp; return; } void addedge(int u,int v) { edge[idx].v = v; edge[idx].next = head[u]; head[u] = idx++; return; } void addmatrix(int x1,int x2,int y1,int y2,int ii) { vertical_line[tot].x = x1; vertical_line[tot].down = y1; vertical_line[tot].up = y2; vertical_line[tot].id = ii; tot++; vertical_line[tot].x = x2; vertical_line[tot].down = y1; vertical_line[tot].up = y2; vertical_line[tot].id = -ii; tot++; yy[top++] = y1; yy[top++] = y2; area[ii] = 1LL * (x2 - x1) * (y2 - y1); return; } void init() { memset(father,-1,sizeof(father)); memset(head,-1,sizeof(head)); tot = top = idx = 0; father[1] = inf; return; } void read() { scanf("%d %d",&w,&h); addmatrix(0,w,0,h,1); int x1,x2,y1,y2; for(int i=2;i<=n+1;i++) { scanf("%d %d %d %d",&x1,&y1,&x2,&y2); if(x1 > x2) swap(x1 , x2); if(y1 > y2) swap(y1 , y2); addmatrix(x1 , x2 , y1 , y2 , i); } sort(vertical_line , vertical_line + tot); sort(yy , yy + top); top = unique(yy , yy + top) - yy; return; } void biuld(int l,int r,int num) { seg[num].l = l; seg[num].r = r; seg[num].lazy = inf; if(l + 1 == r) return; int mid = (l + r) >> 1; biuld(l , mid , num << 1); biuld(mid , r , num << 1 | 1); return; } void DOWN(int num) { if(seg[num].lazy != inf) { seg[num << 1].lazy = seg[num << 1 | 1].lazy = seg[num].lazy; seg[num].lazy = inf; } return; } void UP(int num) { if(seg[num << 1].lazy == seg[num << 1 | 1].lazy) { seg[num].lazy = seg[num << 1].lazy; seg[num << 1].lazy = seg[num << 1 | 1].lazy = inf; } return; } void update(int l,int r,int num,int id) { if(seg[num].l == l && seg[num].r == r) { if(id < 0) seg[num].lazy = father[ABS(id)]; else { father[id] = seg[num].lazy; seg[num].lazy = id; } return; } DOWN(num); int mid = (seg[num].l + seg[num].r) >> 1; if(mid >= r) update(l , r , num << 1 , id); else if(l >= mid) update(l , r , num << 1 | 1 , id); else { update(l , mid , num << 1 , id); update(mid , r , num << 1 | 1 , id); } UP(num); return; } void addline(int i) { int bjd = lower_bound(yy , yy + top , vertical_line[i].down) - yy; int bju = lower_bound(yy , yy + top , vertical_line[i].up) - yy; update(bjd , bju , 1 , vertical_line[i].id); return; } void dfs(int st) { for(int i=head[st];i != -1;i=edge[i].next) { area[st] -= area[edge[i].v]; dfs(edge[i].v); } return; } void solve() { biuld(0 , top - 1 , 1); for(int i=0;i<tot;i++) addline(i); for(int i=2;i<=n+1;i++) addedge(father[i] , i); dfs(1); sort(area + 1 , area + n + 2); for(int i=1;i<=n+1;i++) { if(i > 1) printf(" "); printf("%I64d",area[i]); } puts(""); return; } int main() { while(~scanf("%d",&n)) { init(); read(); solve(); } return 0; }