zoukankan      html  css  js  c++  java
  • 选择数字

    题目描述

    给定一行n个非负整数a[1]..a[n]。现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择。你的任务是使得选出的数字的和最大。

    输入输出格式

    输入格式:

    第一行两个整数n,k

    以下n行,每行一个整数表示a[i]。

    输出格式:

    输出一个值表示答案。

    输入输出样例

    输入样例#1:
    5 2
    1
    2
    3
    4
    5 
    
    输出样例#1:
    12

    说明

    对于20%的数据,n <= 10

    对于另外20%的数据, k = 1

    对于60%的数据,n <= 1000

    对于100%的数据,1 <= n <= 100000,1 <= k <= n,0 <= 数字大小 <= 1,000,000,000

    时间限制500ms

    动归 设f[i]为取前i件物品的最大价值,因为不能连续取k件,所以f[i]的状态可由j∈[i-k+1,i]转移来。

    f[i]=max(f[j]+sum[i]-sum[j+1],f[j-1]+sum[i]-sum[j])

    =max(f[j]-sum[j+1],f[j-1]-sum[j])+sum[i]

    维护一个单调队列就行了

    复杂度O(n)

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 int n,k;
     7 long long sum[100001],f[100001];
     8 long long q[100001],d[100001];
     9 int head,tail=1;
    10 int main()
    11 {
    12     int i,j;
    13     cin>>n>>k;
    14     for (i=1; i<=n; i++)
    15     {
    16         scanf("%lld",&sum[i]);
    17         sum[i]+=sum[i-1];
    18     }
    19     head=0;tail=1;
    20     for (i=1; i<=n; i++)
    21     {
    22         d[i]=f[i-1]-sum[i];
    23         if  (i>=k+1&&d[i-k-1]==q[head]) head++;
    24         while (head<tail&&d[i]>q[tail-1]) tail--;
    25         q[tail++]=d[i];
    26         f[i]=q[head]+sum[i];
    27     }
    28     cout<<f[n];
    29 }
  • 相关阅读:
    nginx 过滤了自定义的请求头参数
    Mysql5.7查看已经执行的sql语句
    Reids5 持久化
    JS 格式化时间,转成 几天前,几个月前
    个人小镜像站点
    记录一次清理Redis 病毒程序 kdevtmpfsi
    laravels 热重启
    Redis 布隆器安装和简单实现
    Redis Zset类型跳跃表算法实现(JAVA)
    Redis5 基于Lua实现分布式排它锁
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7231397.html
Copyright © 2011-2022 走看看