列表

详情


NC221234. 小圆前辈去爬山

描述

今天是周末,天气很好?小圆前辈决定去爬山。她来到了一个有n座山的地方,每座山都有一个编号a,和高度h。由于她是一个,坚持不懈、自强不息、全力以赴、百折不挠、斗志昂扬、持之以恒、雄心壮志……的人,所以她只会爬比她所在的山高的山且比她当前山的编号大的山,如果她从编号为i的山爬到编号为j的山。

, i < j),那么她将消耗的体力值。当她的体力值小于当前消耗的体力值则无法爬山。

现在有q次询问,每次询问当小圆前辈在 编号为x的山,有w的体力值,能到达的山中编号最大的是多少?

输入描述

第一行两个整数 n,q  表示有n座山,q次询问。

接下来有n行,每行有两个整数a,h表示山的编号,和编号为a的山的高度。

接下来有q行,每行有两个整数x,w表示小圆前辈在编号为x的山上,拥有的体力值为w。

输出描述

有q行,对于每次询问输出一个整数表示能到达的山中编号最大的。

示例1

输入:

5 3
2 3
1 4
5 6
3 7
4 2
1 100
2 14
4 1

输出:

5
3
4

说明:

对于第一次询问,编号为1的山可以到编号为1,3,5的山,且5的编号最大且到5消耗30体力值。所以输出5。
对于第二次询问,编号为2的山可以到编号为2,3,5的山,到编号为5的山消耗24体力值无法到达,到编号为3的山消耗14的体力值。所以输出3。
对于第三次询问,编号为4的山可以到编号为编号为4,5的山,到编号为5的山要消耗12体力值,所以只能在原地输出4。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 897ms, 内存消耗: 34600K, 提交时间: 2021-04-27 19:19:58

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const ll N=507;
ll n,q,h[N],d[N][N];
void init(){
	memset(d,0x3f,sizeof(d));
	for(int i=1;i<=n;i++){
		d[i][i]=0;
		for(int j=1;j<i;j++){
			if(h[i]>h[j]){
				d[j][i]=(i-j+1)*h[i];
			}
		}
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=n-1;j>=1;j--){
			d[i][j]=min(d[i][j],d[i][j+1]);
		}
	}
}
bool check(ll p,ll x,ll z){
	if(d[p][x]<=z){
		return true;
	}
	else{
		return false;
	}
}
int main(){
	scanf("%lld%lld",&n,&q);
	for(int i=1;i<=n;i++){
		ll p,z;
		scanf("%lld%lld",&p,&z);
		h[p]=z;
	}
	init();
	while(q--){
		ll p,z;
		scanf("%lld%lld",&p,&z);
		ll l=p,r=n,res=p;
		while(l<=r){
			ll mid=(l+r)/2;
			if(check(p,mid,z)){
				l=mid+1;
				res=mid;
			}
			else{
				r=mid-1;
			}
		}
		printf("%lld\n",res);
	}
}

上一题