1. 程式人生 > >hdu1828線段樹(兩次掃描+離散化)

hdu1828線段樹(兩次掃描+離散化)

for 掃描 方向 body 理解 upd sort 有序 ide

題目鏈接

求周長並,思路和註意事項與求面積並類似,我用了最簡單的思路,即x軸做一次線段樹,y軸做一次線段樹。

還有一種方法,只做一次線段樹,在做線段樹的同時求另一個方向的長度,大概的想法我知道,不過在左右區間合並

這個問題上不是很理解。

做了兩個線段樹的題目,分別是求面積並和周長並。這些問題是幾何問題,是二維的,運用線段樹可以先在一個維度

上,得到當前覆蓋的線段的長度。

技術分享圖片
#include<cstdio>
#include<algorithm>
#include<algorithm>
using namespace std;
const int maxn=5010
;//矩形最大個數 struct edge{ int a1,a2,b; int f;//1表示入,-1表示出 edge(){} edge(int _a1,int _a2,int _b,short _f) { a1=_a1,a2=_a2,b=_b,f=_f; } bool operator <(const edge&e){ if(b!=e.b) return b<e.b; else return f>e.f; } }; int num[maxn*2*4]; int
len[maxn*2*4]; void build(int root,int l,int r) { num[root]=len[root]=0; if(l==r)return; int mid=(l+r)/2; build(root*2,l,mid); build(root*2+1,mid+1,r); } void pushUp(int root,int l,int r,int a[]) { if(num[root]!=0)len[root]=a[r+1]-a[l]; else if(l==r)len[root]=0; else len[root]=len[root*2
]+len[root*2+1]; } void update(int root,int L,int R,int f,int l,int r,int a[]) { if(L<=l&&r<=R){ num[root]+=f; pushUp(root,l,r,a); return; } int mid=(l+r)/2; if(L<=mid)update(root*2,L,R,f,l,mid,a); if(mid<R)update(root*2+1,L,R,f,mid+1,r,a); pushUp(root,l,r,a); } int nEx,nEy; edge ex[maxn*2],ey[maxn*2]; int nVx,nVy; int vx[maxn*2],vy[maxn*2]; int bin(int k,int a[],int n) { int l=0,r=n-1,mid; while(l<=r){ mid=(l+r)/2; if(a[mid]==k)return mid; else if(a[mid]>k)r=mid-1; else l=mid+1; } return -1; } int myUnique(int a[],int n) {//有序去重 int sz=1; for(int i=1;i<n;i++){ if(a[i]!=a[i-1])a[sz++]=a[i]; } return sz; } int main() { //freopen("in.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF&&n!=0){ nEx=nEy=nVx=nVy=0; for(int i=0;i<n;i++){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); vx[nVx++]=x1,vx[nVx++]=x2; vy[nVy++]=y1,vy[nVy++]=y2; ex[nEx++]=edge(x1,x2,y1,1); ex[nEx++]=edge(x1,x2,y2,-1); ey[nEy++]=edge(y1,y2,x1,1); ey[nEy++]=edge(y1,y2,x2,-1); } sort(ex,ex+nEx); sort(vx,vx+nVx); nVx=myUnique(vx,nVx); build(1,0,nVx-1); int preL=0,curL=0,tot=0; for(int i=0;i<nEx;i++){ int l=bin(ex[i].a1,vx,nVx); int r=bin(ex[i].a2,vx,nVx)-1; update(1,l,r,ex[i].f,0,nVx-1,vx); preL=curL; curL=len[1]; //printf("%d\n",len[1]); tot+=abs(curL-preL); } //puts("\n"); sort(ey,ey+nEy); sort(vy,vy+nVy); nVy=myUnique(vy,nVy); build(1,0,nVy-1); preL=curL=0; for(int i=0;i<nEy;i++){ int l=bin(ey[i].a1,vy,nVy); int r=bin(ey[i].a2,vy,nVy)-1; update(1,l,r,ey[i].f,0,nVy-1,vy); //printf("%d\n",len[1]); preL=curL; curL=len[1]; tot+=abs(curL-preL); } printf("%d\n",tot); } //while(1); }
View Code

參考資料

http://blog.csdn.net/acvay/article/details/47660595

http://blog.csdn.net/qq_37497322/article/details/75270381

hdu1828線段樹(兩次掃描+離散化)