HDU 1828 線段樹之掃描線之周長並


點擊打開鏈接

題意:給n個矩形,求它們重疊后的周長

思路:用線段樹的掃描線從下到上掃一遍,與面積並思想有些相似面積並,下面重邊的處理相似,但是周長的並需要求的是豎邊的個數然后乘以高度,而面積並求的是底邊的長乘以高度,這里我們用了區間合並時的lnum和rnum,具體下面有注釋

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=50010;
int num[maxn*4],num1[maxn*4],X[maxn],numseg[maxn*4];//numseg是目前加進去了多少條豎邊
bool lnum[maxn*4],rnum[maxn*4];//num代表的是底邊的長度
//lsum代表當前節點所代表的區間左側是否有豎邊,rsum代表當前節點的右側是否有豎邊,與線段樹區間合並很相似
struct edge{
int l,r,h,s;//s為1是下邊,為-1是上邊
edge(){}
edge(int a,int b,int c,int d) : l(a),r(b),h(c),s(d) {}
bool operator <(const edge &n) const{
if(n.h==h) return s>n.s;
return h<n.h;
}
}ss[maxn];
void pushup(int le,int ri,int node){
if(num1[node]){
lnum[node]=rnum[node]=1;
num[node]=ri-le+1;//傳入節點也是和面積並一樣,防止重邊的計算
numseg[node]=2;//加入一條新邊,則多兩條豎邊
}else if(le==ri) num[node]=lnum[node]=rnum[node]=numseg[node]=0;
else{
lnum[node]=lnum[node<<1];
rnum[node]=rnum[node<<1|1];
num[node]=num[node<<1]+num[node<<1|1];
numseg[node]=numseg[node<<1]+numseg[node<<1|1];
if(lnum[node<<1|1]&&rnum[node<<1]) numseg[node]-=2;
//如果左區間的右端點與右區間的左端點都等於1的話,說明這個端點被覆蓋了,所以減去2
}
}
void update(int l,int r,int add,int le,int ri,int node){
if(l<=le&&ri<=r){
num1[node]+=add;
pushup(le,ri,node);
return ;
}
int t=(le+ri)>>1;
if(l<=t) update(l,r,add,le,t,node<<1);
if(r>t) update(l,r,add,t+1,ri,node<<1|1);
pushup(le,ri,node);
}
int main(){
int n;
while(scanf("%d",&n)!=-1){
int k=0,lmax=999999,rmax=-999999;//點的范圍並不大,不需要離散化,只要找到最左邊和最右邊建樹就行了
for(int i=0;i<n;i++){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
lmax=min(lmax,a);
rmax=max(rmax,c);
ss[k++]=edge(a,c,b,1);
ss[k++]=edge(a,c,d,-1);
}
sort(ss,ss+k);
int ans=0,last=0;
for(int i=0;i<k;i++){
if(ss[i].l<ss[i].r) update(ss[i].l,ss[i].r-1,ss[i].s,lmax,rmax-1,1);
ans+=numseg[1]*(ss[i+1].h-ss[i].h);//將豎邊的個數乘以高度加起來
ans+=abs(num[1]-last);//加上底邊的長度,因為這個是長度,不像面積,不管是上邊還是下邊都要加起來
last=num[1];//所以我們將last作為上次的狀態,num[1]大於last說明加入了邊,肯定是要加上的
} //然后如果num[1]小於last說明有一條上邊加入,因為上邊是-1,所以將上邊的值減去了,
//但是我們要加上它,所以用絕對值解決這個問題
printf("%d\n",ans);
}
return 0;
}


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com