P1714切蛋糕(不定区间最值)

Posted iss-ue

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1714切蛋糕(不定区间最值)相关的知识,希望对你有一定的参考价值。

题面

今天是小Z的生日,同学们为他带来了一块蛋糕。这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值。

小Z作为寿星,自然希望吃到的第一块蛋糕的幸运值总和最大,但小Z最多又只能吃M小块(M≤N)的蛋糕。

吃东西自然就不想思考了,于是小Z把这个任务扔给了学OI的你,请你帮他从这N小块中找出连续的k块蛋糕(k≤M),使得其上的幸运值最大。


不定区间长度还是第一次遇到

分析 考虑朴素写法,非常直观。

对于以第i个元素结尾的子段,最大的子段和P(i)可以表示为

P [ i ] = max { sum [ i ] - sum [ j ] , j 属于 [ i-M, i-1 ]

于是有ans = max [ P [ i ] ]

算法的复杂度是O ( N M )

在题目的范围下TLE是必然的

将上面P[i]的计算式改写为

P [ i ] = sum [ i ] - min { sum [ j ] },j属于 [ i-M , i-1 ]

显然,在每次获取 P [ i ] 的时候,Sum [ i ] 是定值,所以 P [ i ] 由 Sum [ j ] 的最小值确定。

于是我们就要想方设法在优于O(M)的时间内实现获取最小的 Sum [ j ] 。

最优时,Sum [ j ] 的性质:

(1)Sum [ j ] ≤ Sum [ x ]  x∈ [ i-M , i-1 ]且x≠j

(2)j∈[ i-M , i-1 ]

枚举加优化

考虑设计这样一个数据结构,在更低的时间复杂度内获取最优Sum [ j ] 。

①单调队列

技术图片
#include <iostream>
using namespace std;
#define max(a,b) (a>b?a:b)
const int maxn=500009;
int a[maxn],zhui[maxn];
int q[maxn],p[maxn],ans=-9999999,spfa[maxn];
int main()
{
    int n,m,tail=0,head=1;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        zhui[i]=zhui[i-1]+a[i];
    }
    for(int i=1;i<=n;i++)
    {
        while(tail>=head&&q[tail]>=zhui[i])    tail--;
        q[++tail]=zhui[i];p[tail]=i;
        while(p[head]+m<=i)    head++;
        spfa[i]=q[head];
    }
    for(int i=1;i<=n;i++)
        ans=max(ans,zhui[i]-spfa[i-1]);
    cout<<ans;
}
View Code

②ST稀疏表

技术图片
#include <bits/stdc++.h> 
using namespace std;
const int maxn=500009;
int a[maxn],zhui[maxn];
int ans=-9999999,dis[maxn][22];
int query(int l,int r){
    int k=log2(r-l+1);
    return min(dis[l][k],dis[r+1-(1<<k)][k]);
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int t;
        cin>>t;
        zhui[i]=zhui[i-1]+t;
        dis[i][0]=zhui[i];
    }
    for(int j=1;j<=log2(n);j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)
            dis[i][j]=min(dis[i][j-1],dis[i+(1<<(j-1))][j-1]);
    }
    for(int i=1;i<=n;i++)
    {
        int l=i-m;//等于是求i-m+1到第i项 
        if(l<0)        l=0;
        ans=max(ans,zhui[i]-query(l,i));
    }
    cout<<ans;
}
View Code

 

以上是关于P1714切蛋糕(不定区间最值)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷—— P1714 切蛋糕

单调队列P1714 切蛋糕

luogu P1714 切蛋糕 |单调队列

[洛谷P1714]切蛋糕

Luogu P1714切蛋糕(面向对象编程首次尝试?)

ZOJ3537 Cake