题解:luogu P10207([JOI 2024 Final] 马拉松比赛 2 / Marathon Race 2)

1. Solution

首先,很显然有一个结论:我们一定只会在最后一次经过某个位置的时候拿这个位置上的球。
所以我们发现可以钦定每一个位置是第几个拿的。

发现一个位置可以被钦定,当且仅当他的左右两边只有一侧有没有钦定的位置,换言之,可以钦定的位置一定是当前没有钦定的位置两端,因此转换成一个关路灯的经典问题,可以使用区间 dp 解决,这里不过多细说。

所以可以得到一个暴力,时间复杂度是 \(\text{O}(qn^2)\)

我们进一步观察,发现,在不考虑从起点出发到第一个钦定的位置的距离,和从最后一个钦定的位置到终点的距离时,先取 \(1\) 或先取 \(n\) 的代价是一定的,由此可以预处理处两个数组,表示先取 \(1\) 或者先取 \(n\),最后一个取 \(i\) 的最小代价,时间复杂度就变成了 \(\text{O}(n^2+qn)\)

我们发现并没有什么优化空间,但是,如果将所有位置去重之后,有 \(m\) 个不同的位置,则代价最小是 \(\frac{m(m+1)}{2}\),所以当 \(m\ge 1000\) 的时候一定不可能有解,全输出 No 即可,最后的时间复杂度就是 \(O(k^2+qn),k=\min(n,1000)\) 的。

2. Code

/*by ChenMuJiu*/
/*略去缺省源和快读快写*/
const int N=5e5+5;
int n,m,q;
int x[N];
namespace Subtask1{
int cnt[1<<14];
int f[1<<14][14];
void solve(){
	for(int i=1;i<(1<<n);i++)
		cnt[i]=cnt[i>>1]+(i&1);
	while(q--){
		int s=read(),t=read(),T=read();
		memset(f,0x3f,sizeof(f));
		for(int i=0;i<n;i++)
			f[1<<i][i]=abs(x[i+1]-s)+1;
		for(int st=1;st<(1<<n);st++){
			for(int i=0;i<n;i++){
				if(!((st>>i)&1))continue;
				int C=((1<<n)-1)^st;
				while(C){
					int j=(C&-C);
					C^=j;
					tomin(f[st^j][__lg(j)],f[st][i]+(cnt[st]+1)*abs(x[i+1]-x[__lg(j)+1])+1);
				}
			}
		}
		int ans=2e9;
		for(int i=0;i<n;i++)
			tomin(ans,f[(1<<n)-1][i]+(n+1)*abs(x[i+1]-t));
		puts(ans<=T?"Yes":"No");
	}
}
}
namespace Subtask2{
int tot;
int tmp[2005],pre[2005],cnt[2005];
ll f[2005][2005][2];
void solve(){
	for(int i=1;i<=n;i++)
		tmp[i]=x[i];
	sort(tmp+1,tmp+n+1);
	tot=unique(tmp+1,tmp+n+1)-tmp-1;
	for(int i=1;i<=n;i++){
		int p=lower_bound(tmp+1,tmp+tot+1,x[i])-tmp;
		cnt[p]++;
	}
	for(int i=1;i<=tot;i++)
		pre[i]=cnt[i]+pre[i-1];
	while(q--){
		int s=read(),t=read(),T=read();
		memset(f,0x3f,sizeof(f));
		f[1][tot+1][0]=abs(s-tmp[1])+cnt[1];
		f[0][tot][1]=abs(s-tmp[tot])+cnt[tot];
		for(int len=tot+1;len>1;len--){
			for(int l=0,r=len-1;r<=tot+1;l++,r++){
				int x=n-(pre[r-1]-pre[l])+1;
				tomin(f[l+1][r][0],f[l][r][0]+x*(tmp[l+1]-tmp[l])+cnt[l+1]);
				tomin(f[l][r-1][1],f[l][r][0]+x*(tmp[r-1]-tmp[l])+cnt[r-1]);
				tomin(f[l+1][r][0],f[l][r][1]+x*(tmp[r]-tmp[l+1])+cnt[l+1]);
				tomin(f[l][r-1][1],f[l][r][1]+x*(tmp[r]-tmp[r-1])+cnt[r-1]);
			}
		}
		ll ans=8e18;
		for(int i=1;i<=tot;i++)
			tomin(ans,min(f[i][i][0],f[i][i][1])+(n+1)*abs(tmp[i]-t));
			
		puts(ans<=T?"Yes":"No");
	}
}
}
namespace Subtask3{
int tot;
int tmp[N],pre[1005],cnt[1005];
ll f[1005][1005][2],g[2][1005];
void solve(){
	for(int i=1;i<=n;i++)
		tmp[i]=x[i];
	sort(tmp+1,tmp+n+1);
	tot=unique(tmp+1,tmp+n+1)-tmp-1;
	if(tot>=1000){
		for(int i=1;i<=q;i++)
			puts("No");
		exit(0);
	}
	for(int i=1;i<=n;i++){
		int p=lower_bound(tmp+1,tmp+tot+1,x[i])-tmp;
		cnt[p]++;
	}
	for(int i=1;i<=tot;i++)
		pre[i]=cnt[i]+pre[i-1];
	memset(f,0x3f,sizeof(f));
	f[1][tot+1][0]=cnt[1];
	for(int len=tot+1;len>1;len--){
		for(int l=0,r=len-1;r<=tot+1;l++,r++){
			int x=n-(pre[r-1]-pre[l])+1;
			tomin(f[l+1][r][0],f[l][r][0]+x*(tmp[l+1]-tmp[l])+(r!=l+1)*cnt[l+1]);
			tomin(f[l][r-1][1],f[l][r][0]+x*(tmp[r-1]-tmp[l])+(l!=r-1)*cnt[r-1]);
			tomin(f[l+1][r][0],f[l][r][1]+x*(tmp[r]-tmp[l+1])+(r!=l+1)*cnt[l+1]);
			tomin(f[l][r-1][1],f[l][r][1]+x*(tmp[r]-tmp[r-1])+(l!=r-1)*cnt[r-1]);
		}
	}

	for(int i=1;i<=tot;i++)
		g[0][i]=min(f[i][i][0],f[i][i][1]);
	
	memset(f,0x3f,sizeof(f));
	f[0][tot][1]=cnt[tot];
	for(int len=tot+1;len>1;len--){
		for(int l=0,r=len-1;r<=tot+1;l++,r++){
			int x=n-(pre[r-1]-pre[l])+1;
			tomin(f[l+1][r][0],f[l][r][0]+1ll*x*(tmp[l+1]-tmp[l])+(r!=l+1)*cnt[l+1]);
			tomin(f[l][r-1][1],f[l][r][0]+1ll*x*(tmp[r-1]-tmp[l])+(l!=r-1)*cnt[r-1]);
			tomin(f[l+1][r][0],f[l][r][1]+1ll*x*(tmp[r]-tmp[l+1])+(r!=l+1)*cnt[l+1]);
			tomin(f[l][r-1][1],f[l][r][1]+1ll*x*(tmp[r]-tmp[r-1])+(l!=r-1)*cnt[r-1]);
		}
	}
	for(int i=1;i<=tot;i++)
		g[1][i]=min(f[i][i][0],f[i][i][1]);
	
	while(q--){
		int s=read(),t=read(),T=read();
		ll ans=8e18;
		for(int i=1;i<=tot;i++){
			tomin(ans,g[0][i]+abs(s-tmp[1])+1ll*(n+1)*abs(tmp[i]-t));
			tomin(ans,g[1][i]+abs(s-tmp[tot])+1ll*(n+1)*abs(tmp[i]-t));
		}
		puts(ans<=T?"Yes":"No");
	}
}
}
signed main(){
	read(n),read(m);
	for(int i=1;i<=n;i++)
		read(x[i]);
	read(q);
	Subtask3::solve();
}
posted @ 2026-05-14 14:09  陈牧九  阅读(3)  评论(0)    收藏  举报