题目链接:https://codeforces.com/problemset/problem/1197/D


题意:

给你一个序列,求一个子序列 a[l]~a[r] 使得该子序列的 sum(l,r)-k*(r-l+1)/m(向上取整)的值是在所有子序列中最大的,并输出最大值

思路:

法一动态规划

dp[i][j] 表示序列到i截止,这一轮已经进行了j次取数(j = (len+m-1)%m)

那么dp[i][j]维护的就是起点为 s = i-j+1-m*t (t>=0)这个集合的最优,这样所有的 dp[i][j] 就可以维护以 i 截止的最优答案了

对于当前i更新有两种情况:

第一种是只取当前这个 a[i] 这个在 dp[i][1] 特判即可

第二种是还要取前面的,dp[i][j] 从 dp[i-1][j-1](因为 dp[i-1][j-1] 所维护的s集合和 dp[i][j] 所维护的s集合是一样的)转移即可(注意边界条件)

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll inf=; int n,m;
ll ans=,dp[][],sum[],a[],k; int main()
{
scanf("%d%d%lld",&n,&m,&k);
for(int i=;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=sum[i-]+a[i];
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++) dp[i][j]=-inf;
}
dp[][]=a[]-k;
for(int i=;i<=n;i++)
{
dp[i][]=a[i]-k;
for(int j=;j<=min(i,m);j++)
{
if(j==) dp[i][j]=max(dp[i][j],dp[i-][m]+a[i]-k);
else dp[i][j]=max(dp[i][j],dp[i-][j-]+a[i]);
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++) ans=max(ans,dp[i][j]);
}
cout<<ans<<endl;
return ;
}

法二:尺取法

多加了一层维护 start_point%m=rnd,进行m次尺取法即可

(在时间够的情况下,搞不清楚当前单调队列弹出几个是最优的,那么就枚举,这样就不用担心前面要弹出什么了,只需在 len%m=0 时判断是否要把起始点重置即可)

即如果当前的和减去 k*t 小于0,那么就重新开始,否则继续加

注意 ans 在每一次向后扩展时都要更新

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=;
ll ans=,n,a[N],m,k; int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=;i<=n;i++) scanf("%lld",&a[i]);
for(int rnd=;rnd<=m;rnd++){
ll len=; ll now=;
for(int i=rnd;i<=n;i++){
if(len%m==) if(now-len/m*k<) now=,len=;
now+=a[i]; len++;
ans=max(ans,now-(len+m-)/m*k);
}
}
cout<<ans<<endl;
return ;
}

法三:前缀和

我们可以发现 m 很小,只有10,而当子段长度能整除以 m 的时候,再添加一个才会使得我们多去减一个 k

我们可以让所有位置对 m 取模,分成 0—m-1 这样的剩余系,我们枚举剩余系,以剩余系中的位置作为结尾求最大值

当我们枚举到剩余系i的时候,我们另所有处于剩余系i的位置上的数 -k,之后我们直接扫一遍序列,不断累加并和 0 求最大值,遇到可结束位置时,与答案取最大值并更新答案

这样子我们可以再 O(nm) 的时间复杂度下做出这道题

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+;
int n,m,k,a[maxn],b[maxn]; int main(){
cin>>n>>m>>k;
for(int i=;i<=n;i++)
cin>>a[i];
ll ans=,s=;
for(int j=;j<m;j++){
for(int i=;i<=n;i++)
if(i%m==j)
b[i]=a[i]-k;
else
b[i]=a[i];
s=;
for(int i=;i<=n;i++){
s=max(s+b[i],0ll);
if(i%m==j)
ans=max(ans,s);
}
}
cout<<ans<<endl;
return ;
}

参考:https://www.cnblogs.com/Forever-666/p/11241525.htmlhttp://blog.leanote.com/post/icontofig/Educational-Codeforces-Round-69

[题解]Yet Another Subarray Problem-DP 、思维(codeforces 1197D)的更多相关文章

  1. 7月15日考试 题解(链表+状压DP+思维题)

    前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...

  2. Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 背包dp

    D. Yet Another Subarray Problem You are given an array \(a_1, a_2, \dots , a_n\) and two integers \( ...

  3. D. Yet Another Subarray Problem 思维 难 dp更好理解

    D. Yet Another Subarray Problem 这个题目很难,我比赛没有想出来,赛后又看了很久别人的代码才理解. 这个题目他们差不多是用一个滑动窗口同时枚举左端点和右端点,具体如下: ...

  4. Educational Codeforces Round 69 D. Yet Another Subarray Problem

    Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 题目链接 题意: 求\(\sum_ ...

  5. Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 【数学+分块】

    一.题目 D. Yet Another Subarray Problem 二.分析 公式的推导时参考的洛谷聚聚们的推导 重点是公式的推导,推导出公式后,分块是很容易想的.但是很容易写炸. 1 有些地方 ...

  6. maximum subarray problem

    In computer science, the maximum subarray problem is the task of finding the contiguous subarray wit ...

  7. UVA11069 - A Graph Problem(DP)

    UVA11069 - A Graph Problem(DP) 题目链接 题目大意:给你n个点.要你找出有多少子串符合要求.首先没有连续的数字,其次不能再往里面加入不论什么的数字而不违反第一条要求. 解 ...

  8. 动态规划法(八)最大子数组问题(maximum subarray problem)

    问题简介   本文将介绍计算机算法中的经典问题--最大子数组问题(maximum subarray problem).所谓的最大子数组问题,指的是:给定一个数组A,寻找A的和最大的非空连续子数组.比如 ...

  9. 【题解】Jury Compromise(链表+DP)

    [题解]Jury Compromise(链表+DP) 传送门 题目大意 给你\(n\le 200\)个元素,一个元素有两个特征值,\(c_i\)和\(d_i\),\(c,d \in [0,20]\), ...

随机推荐

  1. mybatis学习笔记2

    1.获得插入语句执行之后的自增主键 <insert id="insertUser" parameterType="com.mybatis.po.User" ...

  2. [CF960G]Bandit Blues(第一类斯特林数+分治卷积)

    Solution: ​ 先考虑前缀,设 \(f(i, j)\) 为长度为 \(i\) 的排列中满足前缀最大值为自己的数有 \(j\) 个的排列数. 假设新加一个数 \(i+1\) 那么会有: \[ f ...

  3. dataTable获取所有数据

    "drawCallback": function(settings,e) { var api = new $.fn.dataTable.Api( settings ); resul ...

  4. Visual Studio 插件ReSharper:代码生成工具

    下载地址:http://www.jetbrains.com/resharper/download/download-thanks.html?code=RSU&platform=windows ...

  5. JS-04 JS中的函数都是按值传递的

    JS中的函数都是按值传递的 1.传递参数是基本类型 如例子:基本类型传入函数后,函数内部参数生成一个参数副本,把num变量的值赋给num参数,num参数再去参与函数中的运算,但不会影响外面num变量的 ...

  6. Java中的关键字--volatile

    volatile关键字经常用来修饰变量.不过,volatile本身很容易被误用.本篇就介绍一下volatile的原理和使用方式. 在介绍volatile关键字原理前,我们首先要了解JVM运行时的内存分 ...

  7. git 报错

    -bash: git: command not found export PATH=$PATH:/usr/local/git/bin 使用git clone出现 fatal: unable to ac ...

  8. MySQL--11 备份的原因

    目录 一.备份的原因 二.备份的类型 三.备份的方式 四.备份策略 五.备份工具 六.企业故障恢复案例 1.模拟环境 2.模拟恢复数据过程: 一.备份的原因 运维工作的核心简单概括就两件事: 1)第一 ...

  9. 关于springmvc 整合jackson报错问题

    spring mvc 在整合jackson中报错如下 Context initialization failed org.springframework.beans.factory.BeanCreat ...

  10. cookie和session的联系与区别

    Cookie 当你在浏览网站时,WEB服务器会先送一小小的资料放在你的计算机上,Cookie会帮你在网站上所打的文字或是一些选择都记录下来.当你下次再光临同一个网站时,WEB服务器会先看看有没有它上次 ...