2022牛客(4)1007_线段树

1007_Climb Stairs_线段树

题目大意:

有0到n的n+1层楼,除了0层其他每层都有一只血量为ai的怪兽。初始攻击力为a0,攻击力大于等于怪兽血量就可以打败怪兽,打败之后就可以将其血量累加到自身攻击力上。每次都可以选择向下走一层或者在i+1到i+k层中选择一层直接跳过去。问是否可以杀死所有的怪兽。

思路和代码:

从一层楼跳上去的时候,中间没打完的怪兽要一个个退回来打掉。打完之后再跳出去。假设现在站在第i层要向上跳,那么就是说i层以下的所有怪兽都被打败了所以当前力量值为[0,i]的前缀和。如果要跳到r层那么就要满足下图的条件:

所以就用线段树维护区间的ai+pi即可判断是否能跳。

int n , m , k ; 

ll a[N] ;
ll p[N] ;

struct Node{
	int l , r ;
	ll val ;
}tr[N << 2] ;

void pushup(int now){
	tr[now].val = max(tr[now << 1].val , tr[now << 1 | 1].val) ;
}

void build(int now , int l , int r){
	tr[now] = { l , r } ;
	if(l == r){
		tr[now].val = a[l] + p[l] ; return ;
	}int mid = l + r >> 1 ;
	build(now << 1 , l , mid) ;
	build(now << 1 | 1 , mid + 1 , r) ;
	pushup(now) ;
}

ll query(int now , int l , int r){
	if(l <= tr[now].l && tr[now].r <= r) return tr[now].val ;
	int mid = tr[now].l + tr[now].r >> 1 ; 
	
	ll res = -INF ;
	if(l <= mid) res = max(res , query(now << 1 , l , r)) ;
	if(mid < r ) res = max(res , query(now << 1 | 1 , l , r)) ;
	return res ;
}

string solve(){
	cin >> n >> a[0] >> k ;
	
	rep(i , 1 , n) cin >> a[i] ;
	p[0] = a[0] ;
	
	rep(i , 1 , n) p[i] = a[i] + p[i - 1] ;
	
	build(1 , 1 , n) ;
	
	int i = 0 ;

	while(i < n){

		int l = i + 1 ;
		bool flag = 0 ;
		for(int r = l ; r <= n && r <= i + k ; r ++ ){
			ll res = query(1 , l , r) ;
			if(p[i] >= res - p[r]){
				i = r ;
				flag = 1 ;
				break ;
			}
		}
		if(!flag) break ;
		
	}
	
	return i >= n ? "YES\n" : "NO\n" ;
	
}//code_by_tyrii 

小结

说实话难度不大,把区间的划分做的仔细一点就可以得出结论

posted @ 2022-08-01 19:23  tyrii  阅读(41)  评论(0)    收藏  举报