題意:給你n個矩形,要你求出矩形並的輪廓周長。
在做這題之前,建議先解決POJ1151。
在求矩形並面積的時候,我們記錄了線段投影到y軸上被覆蓋的長度,這題同樣要記錄這個值以得到y軸上屬於輪廓的邊長(當然,不是簡單地把這個長加進去,而是加變化值)。不同的是,還要記錄,y軸上有連續的幾段。比如,這時候有兩個線段,線段a(line[i]表示),線段b(line[i-1]),a和b並不相鄰,即這時候,在y軸上有兩條線段,那麼在x軸方向上的屬於輪廓的長度就是2*2*(line[i].x-line[i-1].x),這樣就可以解決這個問題了。(不過discuss裡的資料過不了,當矩形的邊重合在一起,上面的作法對y軸方向上對輪廓的選擇就出現問題了,因為改變數就不一定是輪廓了。)
/*代碼風格更新後 */#include <iostream>#include <cstring>#include <cstdio>#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=10005;int iabs(int x){return x>0?x:-x;}struct Line{int x,y1,y2,flag;Line(){}Line(int a,int b,int c,int d){ x=a;y1=b;y2=c;flag=d; }bool operator<(const Line&b)const{ return x<b.x; }};int n;vector<int> y;vector<Line> line;map<int,int>H;struct node{int lft,rht;int len,cnt,flag;bool isl,isr;int mid(){return MID(lft,rht);}void init(){len=cnt=isl=isr=0;}void fun(int valu){flag+=valu; cnt+=valu;if(flag>0) {isl=isr=1;len=y[rht]-y[lft];}else isl=isr=0,len=0;}};struct Segtree{node tree[N*4];void up(int ind){if(tree[ind].flag>0) {tree[ind].isl=tree[ind].isr=1;tree[ind].cnt=1;tree[ind].len=y[tree[ind].rht]-y[tree[ind].lft];}else if(tree[ind].lft+1==tree[ind].rht){tree[ind].len=0;tree[ind].cnt=0;tree[ind].isl=0;tree[ind].isr=0;}else{tree[ind].len=tree[LL(ind)].len+tree[RR(ind)].len;tree[ind].cnt=tree[LL(ind)].cnt+tree[RR(ind)].cnt;if(tree[LL(ind)].isr&&tree[RR(ind)].isl) tree[ind].cnt--;tree[ind].isl=tree[LL(ind)].isl;tree[ind].isr=tree[RR(ind)].isr;}}void build(int lft,int rht,int ind){tree[ind].lft=lft;tree[ind].rht=rht;tree[ind].init();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].fun(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);}up(ind);}}seg;int main(){while(scanf("%d",&n)!=EOF){y.clear(); H.clear(); line.clear();int x1,y1,x2,y2;for(int i=0;i<n;i++){scanf("%d%d%d%d",&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;int res=0,len=0;seg.build(0,(int)y.size()-1,1);for(int i=0;i<(int)line.size();i++){if(i!=0) res+=seg.tree[1].cnt*(line[i].x-line[i-1].x)*2;seg.updata(H[line[i].y1],H[line[i].y2],1,line[i].flag);res+=iabs(len-seg.tree[1].len);len=seg.tree[1].len;}printf("%d\n",res);}return 0;}
/*代碼風格更新前*/#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int N=5005;int y[N*2];struct Line{ int x,y1,y2,co; void fun(int a,int b,int c,int d){x=a;y1=b;y2=c;co=d;}}line[N*2];struct node{ int left,right,co; int lf,rf,len,cnt; bool isl,isr; int mid(){return left+(right-left)/2;} void change(int a) { co+=a; if(co==0) {len=0;cnt=0;isl=isr=0;} else {len=rf-lf;cnt=1;isl=isr=1;} }};struct Segtree{ node tree[N*8]; void build(int left,int right,int r) { tree[r].left=left; tree[r].right=right; tree[r].len=tree[r].cnt=0; tree[r].isl=tree[r].isr=0; tree[r].lf=y[left]; tree[r].rf=y[right]; if(left+1<right) { int mid=tree[r].mid(); build(left,mid,r*2); build(mid,right,r*2+1); } } void updata(Line e,int r) { if(tree[r].left+1==tree[r].right) { tree[r].change(e.co); } else { if(e.y1<tree[r*2].rf) updata(e,r*2); if(e.y2>tree[r*2+1].lf) updata(e,r*2+1); tree[r].cnt=tree[r*2].cnt+tree[r*2+1].cnt; tree[r].len=tree[r*2].len+tree[r*2+1].len; tree[r].isl=tree[r*2].isl; tree[r].isr=tree[r*2+1].isr; if(tree[r*2].isr&&tree[r*2+1].isl) tree[r].cnt--; } }}seg;int deal(int);int iabs(int a){return a>0?a:-a;}bool cmp(const Line &e1,const Line &e2){ return e1.x<e2.x;}int main(){ int n,d=0; scanf("%d",&n); for(int i=0;i<n;i++) { int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); line[d].fun(x1,y1,y2,1); y[d++]=y1; line[d].fun(x2,y1,y2,-1); y[d++]=y2; } int cnt=deal(d); seg.build(0,cnt-1,1); seg.updata(line[0],1); int ans=seg.tree[1].len; for(int i=1;i<d;i++) { int temp=seg.tree[1].len; ans+=(2*seg.tree[1].cnt*(line[i].x-line[i-1].x)); seg.updata(line[i],1); ans+=iabs(temp-seg.tree[1].len); //printf("x1=%d,x2=%d,temp=%d,len=%d,ans=%d\n",line[i].x,line[i-1].x,temp,seg.tree[1].len,ans); } printf("%d\n",ans); return 0;}int deal(int n){ sort(y,y+n); sort(line,line+n,cmp); int cnt=1; for(int i=1;i<n;i++) { if(y[i]!=y[i-1]) y[cnt++]=y[i]; } return cnt;}