[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;
}


posted @ 2019-03-28 17:18  cloud_9  阅读(145)  评论(0编辑  收藏  举报