[题解]Yet Another Subarray Problem-DP 、思维(codeforces 1197D)
题目链接: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.html、http://blog.leanote.com/post/icontofig/Educational-Codeforces-Round-69
[题解]Yet Another Subarray Problem-DP 、思维(codeforces 1197D)的更多相关文章
- 7月15日考试 题解(链表+状压DP+思维题)
前言:蒟蒻太弱了,全打的暴力QAQ. --------------------- T1 小Z的求和 题目大意:求$\sum\limits_{i=1}^n \sum\limits_{j=i}^n kth ...
- 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 \( ...
- D. Yet Another Subarray Problem 思维 难 dp更好理解
D. Yet Another Subarray Problem 这个题目很难,我比赛没有想出来,赛后又看了很久别人的代码才理解. 这个题目他们差不多是用一个滑动窗口同时枚举左端点和右端点,具体如下: ...
- Educational Codeforces Round 69 D. Yet Another Subarray Problem
Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 题目链接 题意: 求\(\sum_ ...
- Educational Codeforces Round 69 (Rated for Div. 2) D. Yet Another Subarray Problem 【数学+分块】
一.题目 D. Yet Another Subarray Problem 二.分析 公式的推导时参考的洛谷聚聚们的推导 重点是公式的推导,推导出公式后,分块是很容易想的.但是很容易写炸. 1 有些地方 ...
- maximum subarray problem
In computer science, the maximum subarray problem is the task of finding the contiguous subarray wit ...
- UVA11069 - A Graph Problem(DP)
UVA11069 - A Graph Problem(DP) 题目链接 题目大意:给你n个点.要你找出有多少子串符合要求.首先没有连续的数字,其次不能再往里面加入不论什么的数字而不违反第一条要求. 解 ...
- 动态规划法(八)最大子数组问题(maximum subarray problem)
问题简介 本文将介绍计算机算法中的经典问题--最大子数组问题(maximum subarray problem).所谓的最大子数组问题,指的是:给定一个数组A,寻找A的和最大的非空连续子数组.比如 ...
- 【题解】Jury Compromise(链表+DP)
[题解]Jury Compromise(链表+DP) 传送门 题目大意 给你\(n\le 200\)个元素,一个元素有两个特征值,\(c_i\)和\(d_i\),\(c,d \in [0,20]\), ...
随机推荐
- [暑假集训Day4T2]卡拉赞之夜
抹茶学长给的标程可以被卡到O(N2M2)??? 考虑二分答案+暴力check+离散化+卡常数 首先进行离散化,其实判重的话会更快,但是由于矩阵元素大小太大了,hash判重MLE,所以我就直接记录了NM ...
- [fw]Real Mode addressing
Real Mode 在 real mode 中,memory 的使用被限制在 1 MByte(220 bytes) 內,可用的 address 範圍為 0x00000 ~ 0xFFFFF. 由 mem ...
- IIS故障 应用程序池“XXX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误。该进程 ID 为“XXXX”。数据字段包含错误号。
(尝试失败,但觉得有可行性) 参考https://www.cnblogs.com/qidian10/p/6028784.html https://yq.aliyun.com/articles/6434 ...
- 20180105-Python中dict的使用方法
字典是Python中常用的内置数据类型之一. 字典是无序的对象集合,只能通过key-value的方式存取数据,字典是一种映射类型,其次key的必须是可hash的不可变类型.字典中的key必须唯一. 1 ...
- GeneXus笔记本—GeneXusIDE如何切换成中文语言
嘛 有些人可能比较习惯英文IDE,但是有些人就比较难受 所以为了应对各个地区的差异 GeneXus很人性化的自带了一部分国家的语言包 只不过默认是英文 需要改动一下_(:з」∠)_ 右键你的IDE快捷 ...
- JAVA中位数排序
package quickSort; public class QuickSort { private static int count; /** * 测试 * @param args */ publ ...
- vue之click事件绑定
1.@click不光可以绑定方法,也可以就地修改data里的数据 代码示例代码如下: 2.@click绑定多个操作的时候用:隔开 代码示例代码如下: <el-table><el-ta ...
- 【串线篇】Mybatis缓存之二级缓存
1.应用 二级缓存:namespace级别的缓存:SqlSession关闭或者提交以后有效 一级缓存:SqlSession关闭或者提交以后,一级缓存的数据会放在二级缓存中: 二级缓存的使用:mybat ...
- ubuntu 安装php xdebug
windows 安装xdebug https://www.jetbrains.com/help/phpstorm/configuring-xdebug.html 一.下载 下载与PHP版兼容的Xdeb ...
- ubuntu 彻底删除软件
无法获取 dpkg 前端锁 解决办法如下:1.终端输入 ps aux ,列出进程.找到含有apt-get的进程,直接sudo kill PID. 2.强制解锁,命令sudo rm /var/cach ...