Loading

gym102920L Two Buildings (2020-2021 ACM-ICPC, Asia Seoul Regional Contest)决策单调性

题意

给定数组\(h\),求\(max_{1\le i<j\le n}(h[i]+h[j])*(j-i)\)\(1\le n,h[i]\le 1e6\)

分析

  1. 把原式改写为\(max_{1\le i<j\le n}(h[i]-(-h[j]))*(j-i)\),则对于每个平面点\((i,h[i])\),找到它右下角的点\((j,-h[j])\)使得面积最大。

  2. 对于\(i_1<i_2\),若\(h[i_1]\ge h[i_2]\),则取\(i_2\)的地方取\(i_1\)一定更大,所以可以只取\(i\)从左至右升序排列的点。同理,对于\(j_1<j_2\),若\(-h[j_1]\ge -h[j_2]\),则取\(j_1\)的地方取\(j_2\)一定更大,所以可以只取\(j\)从右至左降序排列的点。

  3. 对于点\(i\),若取\(j\)时取得最大值,则对于点\(l<i\),在\([1-j]\)取得最大值;则对于点\(r>i\),在\([j-n]\)取得最大值。所以可以利用决策单调性进行分治。

    1. 对于图中\(l<i\)的点来说,因为\(j\)\(k\)优,所以\(S_1\ge S_2\),得到\(S_1+S3\gt S_2-S_4\)。则对于\(l\)来说,在\(j\)左侧取得最大值。同理可得点\(r>i\),在\([j-n]\)取得最大值。
      决策单调性

代码

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int maxn=1e6+5;
ll h[maxn],a[maxn],b[maxn],ai[maxn],bi[maxn],ans;

void proc(int l,int r,int L,int R)
{
    ll Ans=0,id=L,mid=(l+r)/2;
    for(ll i=L;i<=R;i++)
    {
        ll tmp=(a[mid]-b[i])*(bi[i]-ai[mid]);
        if(tmp>Ans)
        {
            Ans=tmp;
            id=i;
        }
    }
    ans=max(ans,Ans);
    if(l<mid)
        proc(l,mid-1,L,id);
    if(mid<r)
        proc(mid+1,r,id,R);
}

void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>h[i];
        a[i]=h[i];
        b[i]=-h[i];
    }
    int cnt=1,R=n;
    ai[1]=1;
    bi[n]=n;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>a[cnt])
        {
            a[++cnt]=a[i];
            ai[cnt]=i;
        }
    }
    for(int i=n-1;i>=1;i--)
    {
        if(b[i]<b[R])
        {
            b[--R]=b[i];
            bi[R]=i;
        }
    }
    ans=0;
    proc(1,cnt,R,n);
    cout<<ans<<'\n';
}

int main()
{
    ios::sync_with_stdio(false);
    int t=1;
    // cin>>t;
    while(t--)
        solve();

    return 0;
}

参考链接

  1. https://www.wjyyy.top/3870.html
posted @ 2021-03-28 11:24  intmian  阅读(161)  评论(0编辑  收藏  举报