P2034 选择数字

原题链接

题解

不能连续选k个元素 任意每k个元素就有一个不选 每k个点就有一个断点
每个点都有可能是断点 dp求解

sol.1
f[i] 为第i个点为断点且为结尾的最大值
f[i]=max(f[j]+sum[j+1,i1])

sol.2
至少每隔k个点就取一个点,取点和的最小值

code1,优先队列,O(n·logn)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct node
{
    ll v,x;
    bool operator <(const node &b)const {return b.v<v;}
};
ll dp[1000005]={0};
ll a[1000005];
int main()
{
    ll n,k,sum=0;
    cin>>n>>k;
    for(ll i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }

    priority_queue<node> q;
    ll ans=2e18;
    for(ll i=1;i<=n;i++)
    {
        q.push({dp[i-1],i-1});
        while(q.size()&&i-q.top().x>k+1) q.pop();
        dp[i]=a[i];
        if(q.size()) dp[i]+=q.top().v;
        if(i+k>=n)ans=min(ans,dp[i]);
        //cout<<dp[i]<<endl;
    }

    cout<<sum-ans;
    return 0;
}

code2,单调队列,O(n)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll sum[1000005]={0},f[100005]={0};
ll a[1000005];
int main()
{
    ll n,k;
    cin>>n>>k;
    for(ll i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
    }

    deque<ll> q;
    q.push_back(0);
    for(int i=1;i<=n;i++)
    {
        if(q.size()&&i-q.front()>k+1)q.pop_front();

        if(q.size())  f[i]=f[q.front()]+sum[i-1]-sum[q.front()];
        while(q.size()&&f[q.back()]-sum[q.back()]<=f[i]-sum[i]) q.pop_back();
        q.push_back(i);
        //cout<<f[i]<<endl;
    }

    if(q.size()&&n-q.front()>k) q.pop_front();
    cout<<f[q.front()]+sum[n]-sum[q.front()];
    return 0;
}
posted @   纯粹的  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示