D. Yet Another Subarray Problem

这个题目很难,我比赛没有想出来,赛后又看了很久别人的代码才理解。

这个题目他们差不多是用一个滑动窗口同时枚举左端点和右端点,具体如下:

首先枚举0~m,这个是说更新的位置,如果是1 当m==3 就更新1 4 7 10...

如果是2,当m==3 就更新 2 6 8 11....

最后都会被更新的。

核心代码

 for (int j = ; j < n - i; ++j) {
s += sum[j];
if (j % m == ) s -= k;//这个在判断是不是经过了一个区间,如果经过了就-k
ans = max(ans, s - MIN);//这个是在判断这个时候枚举的区间左端点和区间右端点是不是可以更新答案
if (j % m == m - ) MIN = min(MIN, s);//这个就是在更新区间左端点,只有特定的时刻才可以更新,
//只有在区间左端点才可以,因为我要更新的是下一个区间的右端点,如果提前更新了,那么就会被提前用,可能更新不该更新的东西。
//左端点是由s来更新的,所以不需要考虑k的问题,
//这个左端点只有特定时候才可以更新,因为我们枚举了每一个区间为m的起点,意思就是说我们确定了每一个区间
//当j%m==m-1就是说到了区间的右端点,只有这个时候才可以更新,因为这个时候和我们想更新的是下一个区间的右端点,
//所以这个才满足两点之间相隔了若干个k,这样子就可以一 前缀相减+k的个数相减*k。
}
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 3e5 + ;
typedef long long ll;
ll n, m, ans, k, a[maxn], sum[maxn]; int main()
{
ans = ;
scanf("%lld%lld%lld", &n, &m, &k);
for (int i = ; i < n; i++) scanf("%lld", &a[i]);
for(int i=;i<m;i++)//枚举第一个区间的起点
{
for (int j = i; j < n; j++) sum[j - i] = a[j];
ll mins = , s = ;
for(int j=;j<n-i;j++)
{
s += sum[j];
if (j%m == ) s -= k;
ans = max(ans, s - mins);
if (j%m == m - ) mins = min(mins, s);
}
}
printf("%lld\n", ans);
}

后来上网看了题解发现这个题目还可以用dp写,感觉dp好理解很多。

dp[i][j] 表示前以 i 为右端点,对m取余为 j 时的最大值。

所以转移方程就很好写了

j== 0  dp[i][j]=max(dp[i-1][m-1]+a[i]-k,a[i]-k)

j!=0 dp[i][j]=dp[i-1][j-1]+a[i]

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + ;
ll dp[maxn][];
ll a[maxn];
 
int main()
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for (int i = ; i <= n; i++) scanf("%lld", &a[i]);
for(int i=;i<=n;i++)
{
for (int j = ; j < m; j++) dp[i][j] = -inf64;
}
dp[][m - ] = ;
ll ans = ;
for(int i=;i<=n;i++)
{
for(int j=;j<m;j++)
{
if (j == ) dp[i][j] = max(dp[i - ][m - ] + a[i] - k, a[i] - k);
else dp[i][j] = dp[i - ][j - ] + a[i];
ans = max(ans, dp[i][j]);
}
}
printf("%lld\n", ans);
return ;
}

dp

D. Yet Another Subarray Problem 思维 难 dp更好理解的更多相关文章

  1. 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 \( ...

  2. Educational Codeforces Round 61 F 思维 + 区间dp

    https://codeforces.com/contest/1132/problem/F 思维 + 区间dp 题意 给一个长度为n的字符串(<=500),每次选择消去字符,连续相同的字符可以同 ...

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

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

  4. maximum subarray problem

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

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

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

  6. ZOJ Problem Set - 3822Domination(DP)

    ZOJ Problem Set - 3822Domination(DP) problemCode=3822">题目链接 题目大意: 给你一个n * m的棋盘,每天都在棋盘上面放一颗棋子 ...

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

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

  8. 【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集

    [题目] Tree chain problem Problem Description Coco has a tree, whose vertices are conveniently labeled ...

  9. CodeForces 1197D Yet Another Subarray Problem

    Time limit 2000 ms Memory limit 262144 kB Source Educational Codeforces Round 69 (Rated for Div. 2) ...

随机推荐

  1. web.xml被文件加载过程,各节点加载顺序总结

    web.xml被文件加载过程,各节点加载顺序总结 博客分类: J2EE WebXMLSpringServletBean  今天2010-3-11日,上班无事,想来将web.xml项目描述文件的加载过程 ...

  2. redis集群搭建-3.0/4.0版本

    1.  Redis的安装 1.1. Redis的安装 Redis是c语言开发的. 安装redis需要c语言的编译环境.如果没有gcc需要在线安装.yum install gcc-c++ 安装步骤: 第 ...

  3. 【Java】步入OOP 面向对象

    面向对象编程 OOP Object Oriented Programming 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物. 面向对象是相对于面向过程来讲的,面向对 ...

  4. 如何教零基础的人认识Python

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 编程派 PS:如有需要Python学习资料的小伙伴可以加点击下方链接 ...

  5. 图2-4TCP状态转换图

    这张图中描述了TCP中11个状态的转换. 光看这个图我一开始是蒙蔽的,也没有写服务器和客户端的操作流程.不过回头一想,是状态转换,也就是从一个状态到另外一个状态发生了什么,什么条件触发的.这样是不是好 ...

  6. selenium Webdriver多窗口切换

    应用场景: 在页面操作过程中有时候点击某个链接会弹出新的窗口,这时候就需要主机切换到新打开的窗口上进行操作.WebDriver提供了switch_to.window()方法,可以实现在不同的窗口直接切 ...

  7. P1464 Function

    Function 简   单   的   递   归 这道题一开始十分智障地用递归做,虽然知道没那么简单,但还是冒着送死的心态交了一遍,果然,如我所料 样例输入: 密密麻麻,几万行的样例输入 //:) ...

  8. 漫谈LiteOS之开发板-LiteOS移植(基于GD32450i-EVAL)

    1 为什么移植? 嵌入式设备的芯片型号和外设的差异较大,资源有限.而RTOS无法适配集成所有的驱动,因此会先适配部分开发板,然后通过移植使得适配更多的开发板. 可移植性是嵌入式操作系统与普通操作系统的 ...

  9. 9. js屏幕截图

    html2canvas 该脚本允许您直接在用户浏览器上截取网页或部分网页的“屏幕截图”.屏幕截图基于DOM,因此它可能不是真实表示的100%准确,因为它没有制作实际的屏幕截图,而是根据页面上可用的信息 ...

  10. [转载]绕过CDN查找真实IP方法总结

    前言 类似备忘录形式记录一下,这里结合了几篇绕过CDN寻找真实IP的文章,总结一下绕过CDN查找真实的IP的方法 介绍 CDN的全称是Content Delivery Network,即内容分发网络. ...