HDU 1828 Picture
题目链接:HDU-1828
题意为给定一堆矩形,求总周长。
与HDU-1542非常类似,同样是扫描线法。
做法是每次扫到一条线后,答案加上“覆盖总长度”变化的绝对值。即:
ans+=abs(last-sum[1]);
然后横着竖着各来一次即可。
代码如下:
#include<cstdio> #include<set> #include<map> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int MAXN=20010; struct Line { int x1,x2,d; int y; bool operator < (Line x) { return y<x.y; } void operator = (Line x) { x1=x.x1; x2=x.x2; y=x.y; d=x.d; } }; int dict[MAXN]; map<int,int> index; int xx1[MAXN],xx2[MAXN],yy1[MAXN],yy2[MAXN]; set<int> S; Line lines[MAXN]; LL mark[MAXN<<2]; int sum[MAXN<<2]; void modify(LL o,LL l,LL r,LL ml,LL mr,LL num) { if(ml<=l && r<=mr) { mark[o]+=num; if(mark[o]) sum[o]=(dict[r+1]-dict[l]); else if(l==r) sum[o]=0; else sum[o]=sum[o*2]+sum[o*2+1]; } else { LL m=(r-l)/2+l; if(ml<=m) modify(o*2,l,m,ml,mr,num); if(mr>m) modify(o*2+1,m+1,r,ml,mr,num); if(mark[o]) sum[o]=(dict[r+1]-dict[l]); else if(l==r) sum[o]=0; else sum[o]=sum[o*2]+sum[o*2+1]; } } int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif int n; while(scanf("%d",&n)!=EOF) { int dictnum=0; index.clear(); S.clear(); memset(sum,0,sizeof(sum)); memset(mark,0,sizeof(mark)); int ans=0; for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&xx1[i],&yy1[i],&xx2[i],&yy2[i]); S.insert(xx1[i]); S.insert(xx2[i]); } for(set<int>::iterator it=S.begin();it!=S.end();it++) { dict[++dictnum]=*it; index[*it]=dictnum; } for(int i=1;i<=n;i++) { Line tmp; tmp.x1=index[xx1[i]]; tmp.x2=index[xx2[i]]; tmp.y=yy1[i]; tmp.d=1; lines[2*i-1]=tmp; tmp.y=yy2[i]; tmp.d=-1; lines[2*i]=tmp; } sort(lines+1,lines+1+2*n); int last=0; for(int now=1;now<=n*2;now++) { Line ing=lines[now]; modify(1,1,dictnum-1,ing.x1,ing.x2-1,ing.d); ans+=abs(last-sum[1]); last=sum[1]; } dictnum=0; index.clear(); S.clear(); memset(sum,0,sizeof(sum)); memset(mark,0,sizeof(mark)); for(int i=1;i<=n;i++) { S.insert(yy1[i]); S.insert(yy2[i]); } for(set<int>::iterator it=S.begin();it!=S.end();it++) { dict[++dictnum]=*it; index[*it]=dictnum; } for(int i=1;i<=n;i++) { Line tmp; tmp.x1=index[yy1[i]]; tmp.x2=index[yy2[i]]; tmp.y=xx1[i]; tmp.d=1; lines[2*i-1]=tmp; tmp.y=xx2[i]; tmp.d=-1; lines[2*i]=tmp; } sort(lines+1,lines+1+2*n); last=0; for(int now=1;now<=n*2;now++) { Line ing=lines[now]; modify(1,1,dictnum-1,ing.x1,ing.x2-1,ing.d); ans+=abs(last-sum[1]); last=sum[1]; } printf("%d\n",ans); } return 0; }