[USACO5.5]矩形周长Picture
Description:
给你n个矩形,求它们周长的并
Hint:
\(n \le 5000\)
Solution:
分两种情况算,横的和竖的
横的就用2*覆盖区间段数*长度
竖的相邻扫描线相减就行
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=1e5+5,inf=1e9;
int n,m,tot,res,cnt,hd[mxn];
double tr[mxn<<2];
int cov[mxn<<2],sum[mxn<<2],mxl[mxn<<2],mxr[mxn<<2];
double x[mxn];
inline int read() {
char c=getchar(); int x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline void chkmax(int &x,int y) {if(x<y) x=y;}
inline void chkmin(int &x,int y) {if(x>y) x=y;}
struct T {
double l,r,h; int tp,val;
friend bool operator < (T x,T y) {
if(x.h==y.h) return x.tp>y.tp; //两个矩形末边和初边重合,要算两次周长
return x.h<y.h;
}
}t[mxn];
void push_up(int p,int l,int r) {
if(cov[p]) {
tr[p]=x[r+1]-x[l],sum[p]=1,mxl[p]=l,mxr[p]=r;
return ;
}
else if(l==r) tr[p]=0,sum[p]=0,mxl[p]=inf,mxr[p]=0;
else {
tr[p]=tr[ls]+tr[rs];
sum[p]=sum[ls]+sum[rs]-(mxr[ls]+1==mxl[rs]);
mxl[p]=mxl[ls];
mxr[p]=mxr[rs];
}
}
void update(int l,int r,int ql,int qr,int val,int p) {
if(ql<=l&&r<=qr) {
cov[p]+=val;
push_up(p,l,r);
return ;
}
int mid=(l+r)>>1;
if(ql<=mid) update(l,mid,ql,qr,val,ls);
if(qr>mid) update(mid+1,r,ql,qr,val,rs);
push_up(p,l,r);
}
int main()
{
int cas=1; memset(mxl,0x3f,sizeof(mxl)); memset(mxr,0,sizeof(mxr)); //赋初值
while(cas--) {
n=read();
if(n==0) break;
cnt=res=0;
for(int i=0;i<n;++i) {
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
t[++cnt]=(T){b,d,a,a,1}; x[cnt]=b; //加一维时间,原因见上述
t[++cnt]=(T){b,d,c,a,-1}; x[cnt]=d;
}
sort(x+1,x+cnt+1);
sort(t+1,t+cnt+1);
++res;
for(int i=2;i<=cnt;++i)
if(x[i]!=x[i-1]) x[++res]=x[i];
memset(tr,0,sizeof(tr));
memset(cov,0,sizeof(cov));
double ans=0; int pre=0;
for(int i=1;i<cnt;++i) {
int l=lower_bound(x+1,x+res+1,t[i].l)-x;
int r=lower_bound(x+1,x+res+1,t[i].r)-x-1;
update(1,res,l,r,t[i].val,1);
ans+=abs(tr[1]-pre);
pre=tr[1];
ans+=2*(t[i+1].h-t[i].h)*sum[1];
}
ans+=pre;
printf("%d\n",(int)ans);
}
return 0;
}