[题解]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]\), ...
随机推荐
- mybatis学习笔记2
1.获得插入语句执行之后的自增主键 <insert id="insertUser" parameterType="com.mybatis.po.User" ...
- [CF960G]Bandit Blues(第一类斯特林数+分治卷积)
Solution: 先考虑前缀,设 \(f(i, j)\) 为长度为 \(i\) 的排列中满足前缀最大值为自己的数有 \(j\) 个的排列数. 假设新加一个数 \(i+1\) 那么会有: \[ f ...
- dataTable获取所有数据
"drawCallback": function(settings,e) { var api = new $.fn.dataTable.Api( settings ); resul ...
- Visual Studio 插件ReSharper:代码生成工具
下载地址:http://www.jetbrains.com/resharper/download/download-thanks.html?code=RSU&platform=windows ...
- JS-04 JS中的函数都是按值传递的
JS中的函数都是按值传递的 1.传递参数是基本类型 如例子:基本类型传入函数后,函数内部参数生成一个参数副本,把num变量的值赋给num参数,num参数再去参与函数中的运算,但不会影响外面num变量的 ...
- Java中的关键字--volatile
volatile关键字经常用来修饰变量.不过,volatile本身很容易被误用.本篇就介绍一下volatile的原理和使用方式. 在介绍volatile关键字原理前,我们首先要了解JVM运行时的内存分 ...
- git 报错
-bash: git: command not found export PATH=$PATH:/usr/local/git/bin 使用git clone出现 fatal: unable to ac ...
- MySQL--11 备份的原因
目录 一.备份的原因 二.备份的类型 三.备份的方式 四.备份策略 五.备份工具 六.企业故障恢复案例 1.模拟环境 2.模拟恢复数据过程: 一.备份的原因 运维工作的核心简单概括就两件事: 1)第一 ...
- 关于springmvc 整合jackson报错问题
spring mvc 在整合jackson中报错如下 Context initialization failed org.springframework.beans.factory.BeanCreat ...
- cookie和session的联系与区别
Cookie 当你在浏览网站时,WEB服务器会先送一小小的资料放在你的计算机上,Cookie会帮你在网站上所打的文字或是一些选择都记录下来.当你下次再光临同一个网站时,WEB服务器会先看看有没有它上次 ...