POJ 1151 Atlantis(線段樹離散化求面積並)(C++)
阿新 • • 發佈:2018-12-27
題目連結:http://poj.org/problem?id=1151
算是模板題,做這個之前要搞懂離散化。這裡,區間最好用[L,R),要不然有些區間無法計算得到。人比較懶,自己去琢磨,不寫註釋了QAQ。
#include <cstdio> #include <vector> #include <memory.h> #include <algorithm> #define maxn 110 using namespace std; struct Line{ Line(int a,int b,double c,int d):left(a),right(b),y(c),weight(d){} Line(){} int left,right,weight; double y; friend bool operator<(Line p,Line q){ return p.y<q.y; } }; struct Rect{ double x1,y1,x2,y2; }Data[maxn]; struct Node{ int left,right; int cover; }de[8*maxn]; vector<double>Map; vector<Line>line; int n; void BuildTree(int i,int left,int right) { if(left>=right) return; de[i].left=left; de[i].right=right; de[i].cover=0; if(left==right-1) return; int mid=(left+right)>>1; BuildTree(2*i,left,mid); BuildTree(2*i+1,mid,right); } void PushDown(int i) { if(de[i].left!=de[i].right&&de[i].cover!=-2) { de[2*i].cover=de[2*i+1].cover=de[i].cover; de[i].cover=-2; } } void AddQuery(int i,int left,int right,int cover) { if(left>=right) return; if(left<=de[i].left&&de[i].right<=right&&de[i].cover!=-2) { de[i].cover+=cover; return; } if(de[i].left==de[i].right-1) return; PushDown(i); int mid=(de[i].left+de[i].right)>>1; if(right<mid) AddQuery(2*i,left,right,cover); else if(left>=mid) AddQuery(2*i+1,left,right,cover); else { AddQuery(2*i,left,mid,cover); AddQuery(2*i+1,mid,right,cover); } } double GetArea(int i,int left,int right,double height) { if(left>=right) return 0; if(de[i].cover>=1) { int x=de[i].left,y=de[i].right; return height*(Map[y]-Map[x]); } if(de[i].left==de[i].right-1) return 0; int mid=(de[i].left+de[i].right)>>1; if(right<mid) return GetArea(2*i,left,right,height); else if(left>=mid) return GetArea(2*i+1,left,right,height); else { double sum=0; sum+=GetArea(2*i,left,mid,height); sum+=GetArea(2*i+1,mid,right,height); return sum; } } void DiscretSolve() { int i,x,y; sort(Map.begin(),Map.end()); Map.erase(unique(Map.begin(),Map.end()),Map.end()); for(i=0;i<n;++i) { x=lower_bound(Map.begin(),Map.end(),Data[i].x1)-Map.begin(); y=lower_bound(Map.begin(),Map.end(),Data[i].x2)-Map.begin(); line.push_back(Line(x,y,Data[i].y1,1)); line.push_back(Line(x,y,Data[i].y2,-1)); } sort(line.begin(),line.end()); BuildTree(1,0,Map.size()-1); } void AreaUnion() { int i; double ans=0; AddQuery(1,line[0].left,line[0].right,line[0].weight); for(i=1;i<line.size();++i) { ans+=GetArea(1,0,Map.size()-1,line[i].y-line[i-1].y); AddQuery(1,line[i].left,line[i].right,line[i].weight); } printf("Total explored area: %.2lf\n",ans); } int main() { int i,len=1; double a,b,c,d; while(~scanf("%d",&n)) { if(!n) break; Map.clear(); line.clear(); for(i=0;i<n;++i) { scanf("%lf%lf%lf%lf",&Data[i].x1,&Data[i].y1,&Data[i].x2,&Data[i].y2); Map.push_back(Data[i].x1); Map.push_back(Data[i].x2); } DiscretSolve(); printf("Test case #%d\n",len++); AreaUnion(); puts(""); } return 0; }