Codeforces Round #822 (Div. 2)
比赛链接
Codeforces Round #822 (Div. 2)
D. Slime Escape
给一个长度为 \(n\) 的序列以及一个 \(k\),表示当前位于 \(k\) 这个位置,要求该位置的数往左或者右,每次只能加上 \(a[i]\) 一次,且不允许出现负数,问最后能否到 \(0\) 或 \(n+1\)
解题思路
贪心
假设最后到达 \(0\),则每次向左时,一定可能是先向右补充,即必须先向右加上一些正数,再往左移动比较好,故每次往左移动时先看是否往右能补充
- 时间复杂度:\(O(n)\)
代码
// Problem: D. Slime Escape
// Contest: Codeforces - Codeforces Round #822 (Div. 2)
// URL: https://codeforces.com/contest/1734/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=2e5+5;
int t,n,k,a[N];
vector<int> sum,need;
bool ck()
{
sum.clear(),need.clear();
int mn=0,s=0;
for(int i=k+1;i<=n;i++)
{
s+=a[i];
mn=min(mn,s);
if(s>0)
{
sum.pb(s),need.pb(mn);
mn=s=0;
}
}
int res=a[k];
for(int i=k,j=-1;i>=1;i--)
{
while(j+1<need.size()&&res+need[j+1]>=0)
{
j++;
res+=sum[j];
}
if(res+a[i-1]<0)return false;
res+=a[i-1];
}
return true;
}
signed main()
{
for(cin>>t;t;t--)
{
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
bool f=false;
if(ck())f=true;
reverse(a+1,a+1+n);
k=n-k+1;
if(ck())f=true;
puts(f?"YES":"NO");
}
return 0;
}