Picture[矩形周长并][线段树]

文章目录

题目

HDU

思路

扫描线后可知道周长发生变化时导致覆盖长度变化
线段树维护覆盖长度横竖两次即可
标记永久化管理本区间
注意离散化可能 + + − − ++-- ++ 算重
还可以不用算两次,维护线段个数
贡献为 2 ∗ c n t ∗ Δ y + Δ c o v 2*cnt*\Delta_y+\Delta_{cov} 2cntΔy+Δcov

代码

#include<set>    
#include<map>    
#include<stack>    
#include<ctime>    
#include<cstdio>    
#include<queue>    
#include<cmath>    
#include<vector>    
#include<cstring>   
#include<climits>    
#include<iostream>   
#include<algorithm>
using namespace std;
#define LL long long
int read(){
    int f=1,x=0;char c=getchar();
    while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
    while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}
    return f*x;
}
#define lch (u<<1)
#define rch (u<<1|1)
const int MAXN=200000;
const int INF=0x3f3f3f3f;
struct node{
	int l,r,len,cnt,s,t;
}t[4*MAXN+5];
int X[MAXN+5],Y[MAXN+5];
void PushUp(int u){
	if(t[u].cnt) t[u].s=t[u].len,t[u].t=t[u].r-t[u].l+1-t[lch].t-t[rch].t;
	else t[u].s=t[lch].s+t[rch].s,t[u].t=t[lch].t+t[rch].t;
	return ;
}
void Build(int u,int L,int R){
	t[u]=(node){L,R,X[R+1]-X[L],0,0,0};
	if(L==R) return ;
	int Mid=(L+R)>>1;
	Build(lch,L,Mid),Build(rch,Mid+1,R);
	PushUp(u);
	return ;
}
void Modi(int u,int L,int R,int qL,int qR,int p){
	if(qL<=L&&R<=qR){
		t[u].cnt+=p,PushUp(u);
		return ;
	}
	int Mid=(L+R)>>1;
	if(qL<=Mid) Modi(lch,L,Mid,qL,qR,p);
	if(Mid+1<=qR) Modi(rch,Mid+1,R,qL,qR,p);
	PushUp(u);
	return ;
}
struct ad{int l,r,p;};
vector<ad> G[MAXN+5];
int tx1[MAXN+5],ty1[MAXN+5],tx2[MAXN+5],ty2[MAXN+5];
int X1[MAXN+5],Y1[MAXN+5],X2[MAXN+5],Y2[MAXN+5];
int main(){
	int n;
	while(~scanf("%d",&n)&&n){
		int p=0,q=0;
		for(int i=1;i<=n;i++){
			tx1[i]=X1[i]=read(),ty1[i]=Y1[i]=read(),tx2[i]=X2[i]=read(),ty2[i]=Y2[i]=read();
			X[++p]=X1[i],X[++p]=X2[i],Y[++q]=Y1[i],Y[++q]=Y2[i];
		}
		sort(X+1,X+p+1);
		sort(Y+1,Y+q+1);
		p=unique(X+1,X+p+1)-(X+1);
		q=unique(Y+1,Y+q+1)-(Y+1);
		for(int i=1;i<=n;i++){
			X1[i]=lower_bound(X+1,X+p+1,X1[i])-X;
			X2[i]=lower_bound(X+1,X+p+1,X2[i])-X;
			Y1[i]=lower_bound(Y+1,Y+q+1,Y1[i])-Y;
			Y2[i]=lower_bound(Y+1,Y+q+1,Y2[i])-Y;
			G[Y1[i]].push_back((ad){X1[i],X2[i]-1,1});
			G[Y2[i]].push_back((ad){X1[i],X2[i]-1,-1});
		}
		Build(1,1,p-1);
		int ans=0,lst=0;
		for(int i=1;i<=q;i++){
			//ans+=(Y[i]-Y[i-1])*t[1].t;
			for(int j=0;j<(int)G[i].size();j++){
				Modi(1,1,p-1,G[i][j].l,G[i][j].r,G[i][j].p);
				ans+=abs(lst-t[1].s),lst=t[1].s;
			}
			G[i].clear();
		}
		p=0,q=0;
		for(int i=1;i<=n;i++){
			X1[i]=ty1[i],Y1[i]=tx1[i],X2[i]=ty2[i],Y2[i]=tx2[i];			
			X[++p]=X1[i],X[++p]=X2[i],Y[++q]=Y1[i],Y[++q]=Y2[i];
		}
		sort(X+1,X+p+1);
		sort(Y+1,Y+q+1);
		p=unique(X+1,X+p+1)-(X+1);
		q=unique(Y+1,Y+q+1)-(Y+1);
		for(int i=1;i<=n;i++){
			X1[i]=lower_bound(X+1,X+p+1,X1[i])-X;
			X2[i]=lower_bound(X+1,X+p+1,X2[i])-X;
			Y1[i]=lower_bound(Y+1,Y+q+1,Y1[i])-Y;
			Y2[i]=lower_bound(Y+1,Y+q+1,Y2[i])-Y;
			G[Y1[i]].push_back((ad){X1[i],X2[i]-1,1});
			G[Y2[i]].push_back((ad){X1[i],X2[i]-1,-1});
		}
		Build(1,1,p-1);
		lst=0;
		for(int i=1;i<=q;i++){
			//ans+=(Y[i]-Y[i-1])*t[1].t;
			for(int j=0;j<(int)G[i].size();j++){
				Modi(1,1,p-1,G[i][j].l,G[i][j].r,G[i][j].p);
				ans+=abs(lst-t[1].s),lst=t[1].s;
			}
			G[i].clear();
		}
		printf("%d\n",ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值