在求矩形并面积的时候,我们记录了线段投影到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; }