扫描线周长并

P1856 [USACO5.5]矩形周长Picture

周长并的板子

#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
#define re register int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
const int mod=1e9+7;
const int M=1e8+5;
const int N=4e5+5;//?????????? 4e8
struct node
{
	int sum,num,len;
	int lf,rf;
}e[N];
struct line
{
	int l,r,h,state;
}L[N];
int mi=1e18,ma=-1e18;
int n,ans,last,tot;
bool cmp(line i,line j)
{
	if(i.h==j.h)  return i.state>j.state;
	return i.h<j.h;
}
void push(int p,int l,int r)
{
	if(e[p].sum)
	{
		e[p].num=1;
		e[p].len=r-l+1;
		e[p].lf=e[p].rf=1;
	}
	else if(l==r)
	{
		e[p].len=e[p].num=e[p].lf=e[p].rf=0;
	}
	else
	{
		e[p].len=e[ls(p)].len+e[rs(p)].len;
		e[p].num=e[ls(p)].num+e[rs(p)].num;
		if(e[ls(p)].rf&&e[rs(p)].lf)  e[p].num--;
		e[p].lf=e[ls(p)].lf;
		e[p].rf=e[rs(p)].rf;
	}
}
void update(int p,int L,int R,int l,int r,int x)
{
	if(L<=l&&r<=R)
	{
		e[p].sum+=x;
		push(p,l,r);
		return;
	}
	int mid=(l+r)>>1;
	if(L<=mid)  update(ls(p),L,R,l,mid,x);
	if(mid<R)  update(rs(p),L,R,mid+1,r,x);
	push(p,l,r);
}
void solve()
{
	cin>>n;
	for(re i=1;i<=n;i++)
	{
		int x1,y1,x2,y2;
		scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
		ma=max(ma,max(x1,x2));
		mi=min(mi,min(x1,x2));
		L[++tot]=(line){x1,x2,y1,1};
		L[++tot]=(line){x1,x2,y2,-1};
	}
	if(mi<=0)
	{
//		mi=abs(mi);
		for(re i=1;i<=tot;i++)
		{
			L[i].l+=-mi+1;
			L[i].r+=-mi+1;
		}
		ma+=-mi;
	}
	sort(L+1,L+tot+1,cmp);
	for(re i=1;i<=tot;i++)
	{
		update(1,L[i].l,L[i].r-1,1,ma,L[i].state);
		while(L[i].h==L[i+1].h&&L[i].state==L[i+1].state)
		{
			i++;
			update(1,L[i].l,L[i].r-1,1,ma,L[i].state);
		}
		ans+=abs(e[1].len-last);
		last=e[1].len;
		if(i+1<=tot)  ans+=e[1].num*2*(L[i+1].h-L[i].h);
	}
	cout<<ans<<endl;
}
signed main()
{
    int T=1;
//    cin>>T;
    for(int index=1;index<=T;index++)
    {
//    	printf("Case %d:\n",index);
        solve();
//        puts("");
    }
    return 0;
}
/*


1
6 5
0 0 0 122 499 8888




*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值