Codeforces Round #822 (Div. 2) D. Slime Escape

 

翻译:

你在玩一个叫做Slime Escape的游戏。游戏发生在一条数轴上。最初,有𝑛黏液。对于所有正整数𝑖,其中1≤𝑖≤𝑛,𝑖-th粘液位于位置𝑖,血量𝑎𝑖。你正在控制𝑘位置的黏液。

有两个转义位于位置0和𝑛+1。你的目标是通过执行任意数量的游戏移动达到两个逃脱中的任何一个。

在一个游戏移动中,你将粘液向左或向右移动一个位置。但是,如果在新位置有另一种粘液,你必须吸收它。当你吸收黏液时,你的黏液的血量会随着被吸收黏液的血量而增加,然后被吸收的黏液就会从游戏中消失。

注意,有些黏液可能有负血量,所以当你吸收这些黏液时,你的血量会下降。

如果你的黏液在游戏过程中的任何时刻生命值为负值,你便会立即输掉游戏。

你是否可以在不输掉游戏的情况下执行任意数量的游戏招式而逃脱两次?

输入
每个测试包含多个测试用例。第一行包含单个整数𝑡(1≤𝑡≤20000)—测试用例的数量。测试用例的描述如下。

每个测试用例的第一行包含两个正整数𝑛、𝑘(3≤𝑛≤200000,1≤𝑘≤𝑛)——黏液的数量和黏液的位置。

每个测试用例的第二行包含𝑛整数,𝑎1,𝑎2,…,𝑎𝑛(−109≤𝑎𝑖≤109)—黏液的健康状况。

保证你的黏液的血量是非负的(𝑎𝑘≥0),所有其他黏液的血量都是非零的(𝑖≠𝑘𝑎𝑖≠0)。

可以保证在所有测试用例中𝑛的总和不超过200000。

输出
对于每个测试用例,打印“YES”(不带引号),如果您可以避免丢失,否则打印“NO”(不带引号)。

例子
inputCopy
6
7 4
1 -2 -3 6 -2 -3 -1
3个1
232 -500 -700
7 4
-1 -2 -4 6 -2 -4 -1
8 4
-100 10 -7 6 -2 -3 6 -10
8 - 2
-999 0 -2 3 4 5 6 7
7 3
7 3 3 4 2 1 1
outputCopy
是的
是的
没有
是的
没有
是的
请注意
在第一个测试用例中,你用生命值6控制位置4的黏液。一种方法是吸收5、6、7号位置的黏液。你的粘液在8号位置以0生命值逃逸。

在第二个测试用例中,您控制黏液,在位置1处有232生命值。因为你的黏液已经位于0号位置的逃逸点旁边,你可以在不吸收任何黏液的情况下移动到它。

在第三个测试案例中,我们可以看到,在到达两个逃逸点中的任何一个之前,黏液的生命值总是为负。

在第四个测试用例中,你用生命值6控制位置4的黏液。以下是取胜的可能步骤:

吸收位置5、6、7的黏液:在吸收血量−2的黏液后,你的生命值变为4;吸收血量−3的黏液后变为1;吸收血量为6的黏液后变为7。
吸取位置3和2的黏液:你的生命值变为7−7+10=10。
吸取位置8处的粘液:你的生命值变为10−10=0。
使用9号位置的逃生通道。
因为你的粘液一直保持非负血量,所以你赢了。

 思路:

分成两段,其实从左边出去和从右边出去的情况是一样的,对称的。所以我们在这里只考虑左边或者右边即可。在这里,我们从右边开始讨论,从k位置开始,每次往右走,然后每次加上位置的值,然后根据当前的最大生命值,来每次向左遍历,找到最大的可以吸收的最大值,如果当前的值加上左边最大值小于0,则走不出去。

代码如下:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

int k;
ll a[200005];
void solv(){
    cin>>n>>k;
    for (int i =1; i<=n; i++) {
        cin>>a[i];
    }
    ll an=0;
    ll mbd=0;
    ll mbd2=0;
    for (int i =k,j=k; i<=n; i++) {
        an+=a[i];
        if (an+mbd<0) {
            printf("NO\n");return;
        }
        while (mbd2+an+a[j-1]>=0) {
            j--;
            mbd2+=a[j];
            mbd=max(mbd,mbd2);
            if (j==0) {
                printf("YES\n");return;
            }
        }
    }
    printf("YES\n");
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    while (t--) {
        solv();
    }
    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值