1. 程式人生 > >51nod 1206 && hdu 1828 Picture (掃描線+離散化+線段樹 矩陣周長並)

51nod 1206 && hdu 1828 Picture (掃描線+離散化+線段樹 矩陣周長並)

abs tput www. DC 51nod 長度 空格 TP 所有

1206 Picture 技術分享圖片 題目來源: IOI 1998 基準時間限制:2 秒 空間限制:131072 KB 分值: 160 難度:6級算法題 技術分享圖片 收藏 技術分享圖片 關註 給出平面上的N個矩形(矩形的邊平行於X軸和Y軸),求這些矩形組成的所有多邊形的周長之和。 例如:N = 7。(矩形會有重疊的地方)。 技術分享圖片 合並後的多邊形: 技術分享圖片 多邊形的周長包括裏面未覆蓋部分方塊的周長。 Input
第1行:1個數N。(2 <= N <= 50000)
第2 - N + 1行,每行4個數,中間用空格分隔,分別表示矩形左下和右上端點的坐標。(-1000000 <= X[i], Y[i] <= 1000000)
Output
輸出多邊形的周長。
Input示例
7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16
Output示例
228

思路:
矩陣周長並模板題,hdu1828不需要離散化。。51nod上數據範圍變大了需要離散化處理,寫法和矩陣面積並差不多,多加了幾個數組維護。
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define
mid int m = (l + r) >> 1 const int M = 1e5+10; int cnt[M<<2]; //表示這個區間被重復覆蓋了幾次 int len[M<<2]; // 這個區間被覆蓋的長度 int lp[M<<2],rp[M<<2]; //標記量,表示這個節點左右兩個端點沒有被覆蓋,有則為1,無為0 int num[M<<2]; //這個區間被多少線段覆蓋 int x[M<<2]; struct node{ int h,l,r; int s; node(){} node(
int a,int b,int c,int d):l(a),r(b),h(c),s(d){} bool operator < (const node &cmp) const { if(h == cmp.h) return s > cmp.s; return h < cmp.h; } }t[M<<2]; void pushup(int l,int r,int rt){ if(cnt[rt]){ lp[rt] = rp[rt] = 1; num[rt] = 2; len[rt] = x[r+1] - x[l]; } else if(l == r){ num[rt] = len[rt] = lp[rt] = rp[rt] = 0; } else{ lp[rt] = lp[rt<<1]; rp[rt] = rp[rt<<1|1]; len[rt] = len[rt<<1] + len[rt<<1|1]; num[rt] = num[rt<<1] + num[rt<<1|1]; if(lp[rt<<1|1]&&rp[rt<<1]) num[rt] -= 2; // 左右兩邊兩條線重合,變成一條線段 } } void update(int L,int R,int c,int l,int r,int rt){ if(L <= l&&R >= r){ cnt[rt] += c; pushup(l,r,rt); return; } mid; if(L <= m) update(L,R,c,lson); if(R > m) update(L,R,c,rson); pushup(l,r,rt); } int main() { int n; while(cin>>n){ int m = 0; while(n--){ int a,b,c,d; cin>>a>>b>>c>>d; x[m] = a; t[m++] = node(a,c,b,1); x[m] = c; t[m++] = node(a,c,d,-1); } int k = 1; sort(x,x+m); sort(t,t+m); for(int i = 1;i < m;i ++){ if(x[i] != x[i-1]) x[k++] = x[i]; } memset(cnt,0,sizeof(cnt)); memset(num,0,sizeof(num)); int ret = 0,last = 0; for(int i = 0;i < m;i ++){ int l = lower_bound(x,x+k,t[i].l)-x; int r = lower_bound(x,x+k,t[i].r)-x-1; if(l <= r) update(l,r,t[i].s,0,k-1,1); ret += num[1]*(t[i+1].h - t[i].h); ret += abs(len[1] - last); last = len[1]; } cout<<ret<<endl; } return 0; }

51nod 1206 && hdu 1828 Picture (掃描線+離散化+線段樹 矩陣周長並)