題意:有T組測試資料,每組資料先給一個數字N,接下來的N行裡,每行四個浮點數表示矩形的左上方座標和右下角座標,要求這些矩形至少覆蓋過兩次的面積。
與POJ 1151 Atlantis 的差別是,我們在答案裡加上的不是覆蓋一次的長度乘以兩條線之間x座標的差,而是用覆蓋兩次的長度,那麼問題就變成如果從覆蓋一次的面積得到覆蓋兩次的面積。
為敘述方便,我們假設len[2]為當前線段被覆蓋了兩次的長度,len[1]為當前線段被覆蓋了一次的長度,而len[0]就是這條線段的長度,並且滿足len[2]+len[1]=len[0]。
首先,如果當前這條線段已經被覆蓋了兩次了,那麼這條線段的len[2]就應該等於len[0],而len[1]就應該等於0。
其次,如果當前這條線段被覆蓋了一次,那麼這條線段的len[2]就應該是,左右子線段的len[2]的和加上左右子線段的len[1],當然,前提是當前線段不能是線段樹中的葉子結點,否則它就沒有左右子線段不是嗎?這時候,當前線段的len[2]就應該等於0。而len[1]就等於len[0],最後要注意當前線段的len[1]要減去len[2],以滿足len[1]+len[2]=len[0]。
最後,如果這條線段沒有被覆蓋過,並且當前線段不是線段樹裡的葉子結點,那麼它的len[1]和len[2]都應該從它的左右子線段的len[1]和len[2]得到,如果是葉子結點,那麼len[1]和len[2]都等於0。
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <map>#include <algorithm>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=2000;struct Line{int flag;double x,y1,y2;Line(){}Line(double a,double b,double c,int d){ x=a;y1=b;y2=c;flag=d; }bool operator<(const Line &b)const{ return x<b.x; }};struct node{int lft,rht,flag;double len[3];int mid(){return MID(lft,rht);}void init(){memset(len,0,sizeof(len));}};int n;vector<double> y;vector<Line> line;map<double,int> H;struct Segtree{node tree[N*4];void calu_len(int ind){if(tree[ind].flag>=2){tree[ind].len[2]=tree[ind].len[0];tree[ind].len[1]=0;}else if(tree[ind].flag==1){if(tree[ind].lft+1==tree[ind].rht) tree[ind].len[2]=0;else tree[ind].len[2]=tree[LL(ind)].len[2]+tree[RR(ind)].len[2] +tree[LL(ind)].len[1]+tree[RR(ind)].len[1];tree[ind].len[1]=tree[ind].len[0];tree[ind].len[1]-=tree[ind].len[2];}else{if(tree[ind].lft+1==tree[ind].rht)tree[ind].len[1]=tree[ind].len[2]=0;else{tree[ind].len[2]=tree[LL(ind)].len[2]+tree[RR(ind)].len[2];tree[ind].len[1]=tree[LL(ind)].len[1]+tree[RR(ind)].len[1];}}}void build(int lft,int rht,int ind){tree[ind].lft=lft;tree[ind].rht=rht;tree[ind].init();tree[ind].flag=0;tree[ind].len[0]=y[rht]-y[lft];if(lft+1!=rht){int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid,rht,RR(ind));}}void updata(int st,int ed,int ind,int valu){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed) tree[ind].flag+=valu;else{int mid=tree[ind].mid();if(st<mid) updata(st,ed,LL(ind),valu);if(ed>mid) updata(st,ed,RR(ind),valu);}calu_len(ind);}}seg;int main(){int t;scanf("%d",&t);while(t--){y.clear(); H.clear(); line.clear();scanf("%d",&n);double x1,y1,x2,y2;for(int i=0;i<n;i++){scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);line.push_back(Line(x1,y1,y2,1));line.push_back(Line(x2,y1,y2,-1));y.push_back(y1); y.push_back(y2);}sort(line.begin(),line.end());sort(y.begin(),y.end());y.erase(unique(y.begin(),y.end()),y.end());for(int i=0;i<(int)y.size();i++) H[y[i]]=i;seg.build(0,(int)y.size()-1,1);double res=0;for(int i=0;i<(int)line.size();i++){if(i!=0) res+=(line[i].x-line[i-1].x)*seg.tree[1].len[2];seg.updata(H[line[i].y1],H[line[i].y2],1,line[i].flag);}printf("%.2lf\n",res);}return 0;}