1. 程式人生 > >poj1177 矩形周長並

poj1177 矩形周長並

線段樹掃描線的模板題,一個月前寫的發現忘了一些還是要看看以前的部落格呀!

/*
思路:資料小不用離散化處理,線段樹葉子結點維護一個區間
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 20005
struct Seg{
    int l,r,h,s;
    Seg(){}
    Seg(int a,int b,int c,int d):l(a),r(b),h(c),s(d){}
    
bool operator<(const Seg & a)const { //if(h==a.h) return s>a.s; return h<a.h; } }ss[maxn]; bool lbd[maxn<<2],rbd[maxn<<2];//被覆蓋的區域是否和左右區間線重合 int numseg[maxn<<2],cnt[maxn<<2],len[maxn<<2]; void pushup(int rt,int l,int r){ if(cnt[rt]){ lbd[rt]
=rbd[rt]=1; len[rt]=r-l; numseg[rt]=2; } else if(l+1==r) len[rt]=numseg[rt]=rbd[rt]=lbd[rt]=0; else { lbd[rt]=lbd[rt<<1]; rbd[rt]=rbd[rt<<1|1]; len[rt]=len[rt<<1]+len[rt<<1|1]; numseg[rt]=numseg[rt<<1]+numseg[rt<<1
|1]; if(lbd[rt<<1|1] && rbd[rt<<1]) numseg[rt]-=2; } } #define lson l,m,rt<<1 #define rson m,r,rt<<1|1 void update(int L,int R,int c,int l,int r,int rt){ if(L<=l && R>=r){ cnt[rt]+=c; pushup(rt,l,r); return; } int m=l+r>>1; if(L<m) update(L,R,c,lson); if(R>m) update(L,R,c,rson); pushup(rt,l,r); } void init(){ memset(lbd,0,sizeof lbd); memset(rbd,0,sizeof rbd); memset(cnt,0,sizeof cnt); memset(len,0,sizeof len); memset(numseg,0,sizeof numseg); } int main(){ int n; while(scanf("%d",&n)==1){ init(); int m=0,x1,y1,x2,y2,lbd=9999999,rbd=-9999999,last=0,ans=0; for(int i=1;i<=n;i++){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); ss[m++]=Seg(x1,x2,y1,1); ss[m++]=Seg(x1,x2,y2,-1); lbd=min(lbd,x1),rbd=max(rbd,x2); } sort(ss,ss+m); for(int i=0;i<m;i++){ update(ss[i].l,ss[i].r,ss[i].s,lbd,rbd,1); ans+=abs(len[1]-last);last=len[1]; ans+=numseg[1]*(ss[i+1].h-ss[i].h); } printf("%d\n",ans); } return 0; }