D. Slime Escape codeforce(贪心)

42 篇文章 0 订阅

You are playing a game called Slime Escape. The game takes place on a number line. Initially, there are $$$n$$$ slimes. For all positive integers $$$i$$$ where $$$1 \le i \le n$$$, the $$$i$$$-th slime is located at position $$$i$$$ and has health $$$a_i$$$. You are controlling the slime at position $$$k$$$.

There are two escapes located at positions $$$0$$$ and $$$n+1$$$. Your goal is to reach any one of the two escapes by performing any number of game moves.

In one game move, you move your slime to the left or right by one position. However, if there is another slime in the new position, you must absorb it. When absorbing a slime, the health of your slime would be increased by the health of the absorbed slime, then the absorbed slime would be removed from the game.

Note that some slimes might have negative health, so your health would decrease when absorbing such slimes.

You lose the game immediately if your slime has negative health at any moment during the game.

Can you reach one of two escapes by performing any number of game moves, without ever losing the game?

题意:有n个数,最开始从k开始走,每次可以向左或者向右走,走到第i个位置时加上a[i]这个数,如果加上a[i]之后这个数小于0的话我们就不能走到i,走到最左边或者最右边算成功,那么我们能否走成功。

思路:假设我们都向左走的话

我们先贪心的让他最大,看看向右走能不能让他加上所有能加到的正数

如果能的话我们就加上这个正数再向左走一步,如果加上了所有能加上的正数向左走一步的话<0

就说明不能向左走

然后我们再考虑向右走的话就是把数组翻转过来向左走

这个时候我们要注意,正着的数组的坐标是k,那么翻转过来后在新数组的下标op就是n-k+1

然后再从op向左走

那么我们再想想怎么能让他向右加上所有加的正数

比如说我们现在的数走到i,当前的数是sum,右边的数是 -2 -3 6 -1 -4 7

那么我们走到6的时候就加上了一个正数1,但是我们要走到6的话我们得先满足我们本身这个数sum得大于-2+-3=-5,如果能满足的话我们加上1这个正数,向右继续看能不能走到7,如果不能满足的话说明我们到不了6,那么直接跳出

/*

 .----------------.  .----------------.  .----------------.  .----------------. 
| .--------------. || .--------------. || .--------------. || .--------------. |
| |  ________    | || |  _________   | || | ____    ____ | || |     ____     | |
| | |_   ___ `.  | || | |_   ___  |  | || ||_   \  /   _|| || |   .'    `.   | |
| |   | |   `. \ | || |   | |_  \_|  | || |  |   \/   |  | || |  /  .--.  \  | |
| |   | |    | | | || |   |  _|  _   | || |  | |\  /| |  | || |  | |    | |  | |
| |  _| |___.' / | || |  _| |___/ |  | || | _| |_\/_| |_ | || |  \  `--'  /  | |
| | |________.'  | || | |_________|  | || ||_____||_____|| || |   `.____.'   | |
| |              | || |              | || |              | || |              | |
| '--------------' || '--------------' || '--------------' || '--------------' |
 '----------------'  '----------------'  '----------------'  '----------------'

*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<cmath>
#include<stack>
#define int long long
#define lowbit(x) x&(-x)
#define PI 3.1415926535
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int gcd(int a,int b){
	return b>0 ? gcd(b,a%b):a;
}
/*
int dx[8]={-2,-2,-1,1,2,2,-1,1};
int dy[8]={-1,1,2,2,1,-1,-2,-2};
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
int dx[8]={-1,1,0,0,-1,-1,1,1};
int dy[8]={0,0,-1,1,-1,1,-1,1};
*/
//int e[N],ne[N],h[N],idx,w[N];
/*void add(int a,int b,int c){
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
*/
const int N=2e5+10;
int n,k;
int a[N];
bool work(){
	vector<int> v,m;
	int sum=0,mi=0;//预处理右边
	for(int i=k+1;i<=n;i++){
		sum+=a[i];
		if(sum<0)mi=min(mi,sum);//当他加上这个数小于0的时候我们把最小的数存一下
		else{
			v.push_back(sum);//当他大于0的时候我们就把这个正数存一下,把到达这个正数需要加的最小负数存一下
			m.push_back(mi);
			sum=0;
			mi=0;  
		}
	}
	int j=0;
	sum=0;
	for(int i=k;i>=1;i--){
		for(;j<v.size() ;j++){//看看向右最多能加多少个正数
			if(sum>=-m[j]){//如果他比到达这个正数之前需要的负数大的话就加上这个正数
				sum+=v[j];
			}else break;//否则的话不能到达这个正数
		}
		sum+=a[i];
		if(sum<0)return false;
	}
	return true;
}
void sove(){
	cin>>n>>k;
	for(int i=1;i<=n;i++)cin>>a[i];
	if(work()){
		cout<<"YES"<<endl;
		return ;
	}
	reverse(a+1,a+1+n);
	k=n-k+1;
	if(work()){
		cout<<"YES"<<endl;
		return ;
	}
	cout<<"NO"<<endl;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie() ,cout.tie() ;
	int t=1;
	cin>>t;
	while(t--){
		sove();
	}
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值