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;
}
posted @ 2022-09-24 22:39  zyy2001  阅读(54)  评论(0编辑  收藏  举报