D. Yet Another Subarray Problem 思维 难 dp更好理解
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更好理解的更多相关文章
- 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 \( ...
- Educational Codeforces Round 61 F 思维 + 区间dp
https://codeforces.com/contest/1132/problem/F 思维 + 区间dp 题意 给一个长度为n的字符串(<=500),每次选择消去字符,连续相同的字符可以同 ...
- Educational Codeforces Round 69 D. Yet Another Subarray Problem
Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 题目链接 题意: 求\(\sum_ ...
- maximum subarray problem
In computer science, the maximum subarray problem is the task of finding the contiguous subarray wit ...
- 动态规划法(八)最大子数组问题(maximum subarray problem)
问题简介 本文将介绍计算机算法中的经典问题--最大子数组问题(maximum subarray problem).所谓的最大子数组问题,指的是:给定一个数组A,寻找A的和最大的非空连续子数组.比如 ...
- ZOJ Problem Set - 3822Domination(DP)
ZOJ Problem Set - 3822Domination(DP) problemCode=3822">题目链接 题目大意: 给你一个n * m的棋盘,每天都在棋盘上面放一颗棋子 ...
- Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 【数学+分块】
一.题目 D. Yet Another Subarray Problem 二.分析 公式的推导时参考的洛谷聚聚们的推导 重点是公式的推导,推导出公式后,分块是很容易想的.但是很容易写炸. 1 有些地方 ...
- 【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集
[题目] Tree chain problem Problem Description Coco has a tree, whose vertices are conveniently labeled ...
- CodeForces 1197D Yet Another Subarray Problem
Time limit 2000 ms Memory limit 262144 kB Source Educational Codeforces Round 69 (Rated for Div. 2) ...
随机推荐
- spring singleton实例中的变量怎么保证线程安全
pring中管理的bean实例默认情况下是单例的[sigleton类型],就还有prototype类型按其作用域来讲有sigleton,prototype,request,session,global ...
- 数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数
包.变量和函数 一.举个例子 现在我们来建立一个完整的程序main.go: // Golang程序入口的包名必须为 main package main // import "golang&q ...
- 数据结构和算法(Golang实现)(12)常见数据结构-链表
链表 讲数据结构就离不开讲链表.因为数据结构是用来组织数据的,如何将一个数据关联到另外一个数据呢?链表可以将数据和数据之间关联起来,从一个数据指向另外一个数据. 一.链表 定义: 链表由一个个数据节点 ...
- GeoGebra动态效果
1.动态绘出f(x) 使用SlowPlot指令 2.GeoGebra的动态来源于两个:滑动条(Slider)和动点(Point) silder简单使用 动点的使用,右击,trace on,如果需要固定 ...
- MySQL系列操作
Linux环境下安装使用MySQL Portal 数据备份&恢复 Portal
- testNG 断言
testNG提供一个Assert类,来判断输出值是否与预期值一致,Assert常用的方法有: Assert.assertEquals():此方法可以有两个参数值,也可以有3个参数值,参数的顺序是 ac ...
- 用pytorch做手写数字识别,识别l率达97.8%
pytorch做手写数字识别 效果如下: 工程目录如下 第一步 数据获取 下载MNIST库,这个库在网上,执行下面代码自动下载到当前data文件夹下 from torchvision.dataset ...
- 模拟电磁曲射炮_H题 方案分析【2019年电赛】【刘新宇qq522414928】
请查看我的有道云笔记: 文档:电磁曲射炮分析.note链接:http://note.youdao.com/noteshare?id=26f6b6febc04a8983d5efce925e92e21
- 关于unix环境高级编程、Linux程序设计两部书浅谈
unix环境高级编程的术语很多,概念内容,也很多,不过学习概念性质.标准规则类的东西,想必都是这样吧——需要进行拓展的内容很多. Linux程序设计,图文并茂,代码量够足,看起来,感觉难度还可以. l ...
- Python初学者常见错误问题汇总
1.在客户端和服务端如何传递数组? 答:在客户端和服务端可以使用json进行数据传输.在客户端把数据转换成json字符串,然后使用POST方法发送给服务端. 服务端收集到数据之后,使用json.loa ...