2019牛客多校第⑨场J Symmetrical Painting(思维,离散化)

原题:https://ac.nowcoder.com/acm/contest/889/J

题意:

二维平面上有n个矩形,每个矩形左下角是(i−1,Li)(i−1,Li), 右上角是(i,Ri)(i,Ri),矩形一开始全是黑色,平面不被矩形覆盖的地方是白色,你要把某些黑色区域涂白(一个矩形可以内部颜色不一样),使得黑色区域是一个轴对称图形并且对称轴平行于x轴,求最大黑色区域面积

思路:

经过分析发现ans关于对称轴y是一个线性的函数,而函数的最大值点只可能在 中线处取到,因此我们只需要从下往上枚举每条中线,但是y在矩形下半部分移动和在上半部分移动,这个矩形的ans关于y的单调性是相反的,因此我们需要把矩形分为上半部分和下半部分,分别维护两个集合的大小down和up(对称轴在移动过程中经过的部分矩形有多少个),下半部分的集合对答案的贡献就是(down * 移动距离 * 2)​ ,上半部分集合对答案的贡献是(-up * 移动距离 * 2)。
为了down和up能O(1)快速更新,需要预处理每次移动两个集合的变化。可以将每条边(底线,中线,上线)离散化,从下往上枚举离散化后的坐标,记录每次底线、中线、上线的变化数量。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=3e5+5;
int l[maxn],r[maxn],mid[maxn];
int a[maxn*3];
int in[maxn*3],out[maxn*3],change[maxn*3];
int main(){
	ll n;
	cin>>n;
	ll size=0;
	for(ll i=1;i<=n;i++){
		scanf("%d%d",&l[i],&r[i]);
		l[i]=l[i]*2-1;//l[i]<=2e9
		r[i]=r[i]*2-1;
		mid[i]=((ll)l[i]+r[i])>>1;
		a[++size]=l[i];
		a[++size]=r[i];
		a[++size]=mid[i];
	}
	sort(a+1,a+1+size);
	size=unique(a+1,a+1+size)-(a+1);
	for(ll i=1;i<=n;i++){
		in[lower_bound(a+1,a+1+size,l[i])-a]++;
		change[lower_bound(a+1,a+1+size,mid[i])-a]++;
		out[lower_bound(a+1,a+1+size,r[i])-a]++;
	}
	ll down=0,up=0;//下半矩形个数和上半矩形个数 
	ll temp=0,ans=0;
	down+=in[1];
	for(ll i=2;i<=size;i++){//第一条是下线,对答案无贡献
		temp+=((ll)(down-up)*(a[i]-a[i-1]));
		ans=max(temp,ans);
		down+=in[i];
		down-=change[i];
		up+=change[i];
		up-=out[i];
	}
	printf("%lld\n", ans);
}
posted @ 2019-08-16 12:07  UCPRER  阅读(213)  评论(0编辑  收藏  举报