Problem - A - Codeforces
题意:
给你一串序列,任意从什么地方开始,给你k秒时间,让你算最大价值
每一秒时间按顺序你可以做:
①移动到|x-y|<=1的地方
②取走这个位置上所有的数
③每个位置+1
原来是0秒,从第一秒开始计时
感悟:
这一题我的思维有点混乱,不是特别明朗,但是该考虑的点我都考虑了一遍,可能在想其他的时候,原来想的忘记了...比如我刚想到分情况,又跳到了另一个点上,最后忘记了分情况,以后记得把重点写下来。分析的时候思路也不是特别明朗,奇怪的思路这里就先不说了,分析一下正解
分析:
首先这样子的应该先想到分情况去讨论,k<=n和k>n的情况,因为两种走的方式完全不一样
第一种k<=n貌似更好考虑一些:
假设没有增加的量,那走法并不会出现原地跳或者来回跳,可以想到的是连续的k个地方去取,然后我们可以看看加上增加量,取连续k个位置是不是正解
因为如果没有增加量,每个区间都是定值。这里可以单独考虑一下增加值:增加量与时间成正比,以位置作为观察量可知,走到某个位置的时间t[i]是固定的,所以不管是不是来回走每个位置所取走的量都是最后一次走到那个位置t[i]-1
所以看看是否正解:总的价值即------->为x个数连加,如果存在来回跳的话,每一个位置取最后走到的t[i]-1,这些和相加,最大的秒数只有k秒,来回跳,经过的越少,所以起步越大,例如:3+4+...+7,如果不会来回跳就是0+1+2+3+4+...+7,贪心策略就可以看出来了。所以在这种情况,不可能存在来回跳的情况,后面的时间是定值,最大价值即一段连续k个值的和最大,这个好说,直接遍历一遍就好
第二种情况k>n:
那这个肯定有来回跳的情况了,这个我们依然需要把全部的数加上,最大的增加值即为k-1+k-2+k-3+...+k-n+1,因为相加的个数都是n,当然越大越好,起步越大越好。
具体见代码:
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define IOS ios::sync_with_stdio(false), cin.tie(0);
#include<iostream>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PAII;
const int N=2e6+10,M=5050,INF=1e18,mod=1e9+7;
int a[N],s[N];
signed main(){
IOS;
int T;
//T=1;
cin>>T;
while(T--)
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
if(k<=n)
{
int maxn=-1;
for(int i=1;i+k-1<=n;i++)
{
int l=i,r=i+k-1;
int x=s[r]-s[l-1];
maxn=max(maxn,x);
}
for(int i=1;i<=k;i++) maxn+=i-1;
cout<<maxn<<"\n";
}
else
{
int res=s[n];
for(int i=1;i<=n;i++) res+=k-i;
cout<<res<<"\n";
}
}
return 0;
}
/*
*/