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

题意:二维平面上有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);
}

猜你喜欢

转载自www.cnblogs.com/ucprer/p/11363093.html