abc417_d Takahashi's Expectation 题解

题目描述:

https://atcoder.jp/contests/abc417/tasks/abc417_d

题目分析:
image

首先观察数据范围,发现P[i],A[i],B[i]的范围很小,都在500以内,而X[i]却可达到10^9

这样,高桥的心情X[i]在前几轮会一直减小,直到500以内

因此,我们可以计算X[i]经过几轮会到500以内,而后进行DP

计算X[i]经过几轮会到500以内,可以提前预处理B数组的前缀和,二分查找,复杂度 O(n * logn)

定义f[maxn][maxk] (maxk=1000,X[]+A[])

f[i][j]表示接到第i件礼物前心情为j的最终心情,从i=n+1倒推即可

总状态数 n * k,转移是 O(1)的,故复杂度 O(n * k),可通过本题

#include <iostream>
#define int long long
using namespace std;
const int MAXN=1e4+7;
const int MAXX=1005;//初始心情降到500以下后的最大值
const int INF=1000;
int val[MAXN],a[MAXN],b[MAXN];
int f[MAXN][MAXX];//收到第i件礼物前心情为j的最终心情
int s[MAXN];
signed main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>val[i]>>a[i]>>b[i];
		s[i]=s[i-1]+b[i];//前缀和
	}
	for(int i=0;i<=INF;i++){
		f[n+1][i]=i;//初始化
	}
	for(int i=n;i>=1;i--){//倒推f数组
		for(int j=0;j<=INF;j++){
			if(val[i]>=j){//增加
				f[i][j]=f[i+1][j+a[i]];
			}else{//减少
				int p=max(0LL,j-b[i]);//别忘了判负
				f[i][j]=f[i+1][p];
			}
		}
	}
	int q;
	cin>>q;
	while(q--){
		int x;
		cin>>x;
		if(x<=INF){//本身就比500小
			cout<<f[1][x]<<endl;
			continue;
		}
		int ans=n+1;
		int l=1,r=n;//经过[l,r]轮后
		while(l<=r){//二分答案
			int mid=(l+r)/2;
			if(x-s[mid]<=INF){
				ans=mid;
				r=mid-1;
			}else{
				l=mid+1;
			}
		}
		if(ans==n+1){//到最后一轮还比500大
			cout<<x-s[n]<<endl;
		}else{
			cout<<f[ans+1][x-s[ans]]<<endl;//注意f[i][j]表示收到第i件礼物"前"
		}
	}
}

完结撒花!

posted @ 2025-08-25 22:02  3flzs  阅读(17)  评论(0)    收藏  举报