YL 模拟赛总结 11

Posted on 2024-03-02 17:05  _XOFqwq  阅读(3)  评论(0编辑  收藏  举报

Problem


T1

略。

T2

略。

T3

结论题。

令所有牛的最终饥饿值为 \(x\),则分别对于每一头牛进行考虑:

  • 对于第一头牛,它需要的最少玉米袋数为 \(h_1-x\)

  • 对于第二头牛,它单独需要的最少玉米袋数为 \(h_2-x\),而第一头牛已经用了 \(h_1-x\) 袋玉米,因此它需要的最少玉米袋数为 \(h_2-x-(h_1-x)=h_2-h_1\)

  • 对于第三头牛,它单独需要的最少玉米袋数为 \(h_3-x\),而第二头牛已经用了 \(h_2-h_1\) 袋玉米,因此它需要的最少玉米袋数为 \(h_3-x-(h_2-h_1)=h_3-h_2+h_1-x\)

  • \(......\)

从上述推导可知,每一头牛需要的最少玉米袋数去掉 \(-x\) 之后每一项都是 \(h_i\) 减去前一项得到,同时每个偶数项均为 \(0\)

而我们又发现,每一项去除 \(-x\) 之后,就变成了最终的饥饿值。

因为每个偶数项均为 \(0\),则真正对于答案有贡献的只有奇数项。

所以 \(s-\min\{m_1\}\) 即为答案,
其中 \(s\) 为初始饥饿值之和,\(m_1\) 为奇数项去除 \(-x\) 之后的值。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int t,n,v,s;
int h[100031],m[2];

void solve(){
	cin>>n,s=0;
	for(int i=1;i<=n;i++) cin>>h[i],s+=h[i];
	if(n==1) cout<<0<<'\n';
	else{
		v=h[1],m[1]=h[1],m[0]=h[2];
		for(int i=2;i<=n;i++)
			v=h[i]-v,m[i%2]=min(m[i%2],v);
		if(min(m[0],m[1])<0||n%2==0&&v) cout<<-1<<'\n';
		else cout<<s-m[1]*n<<'\n';
	}
}

signed main(){
	cin>>t;
	while(t--) solve();
	return 0;
}

T4

显然是 dp。

一种很朴素的做法就是先枚举起点,再对于两个方向进行 dp。但这样做复杂度过高,无法接受。

考虑反向思考:我们往左 / 右方向 dp,其实就相当于从终点往右 / 左方向 dp,这样我们就不用枚举起点,只用考虑方向即可。

具体地,我们对于每个满足 \(1 \le i \le n\)\(i\),枚举它前面的满足 \(1 \le j < i\)\(j\),和满足 \(i < k \le n\)\(dis_{i,k} \ge dis_{j,i}\)\(k\)\(dis_{i,j}\) 表示 \(i,j\) 之间的距离),先取到最大的前置状态 \(dp_{k,i}\),然后 \(i\) 可以选择接上之前路径,也可以单独开辟路径,在两种选择中去最优即可。反之亦然。

#include<bits/stdc++.h>
using namespace std;

int n,ans=-1e9;
pair<int,int> a[1031];
int dp[1031][1031];

int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second,ans=max(ans,a[i].second);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		for(int j=n,k=1,mx=0;j>i;j--){
			for(;k<i&&a[j].first-a[i].first<=a[i].first-a[k].first;k++) mx=max(mx,dp[k][i]);
			dp[i][j]=max(a[i].second+a[j].second,mx+a[j].second);
			ans=max(ans,dp[i][j]);
  		}
	}
	for(int i=n;i>=1;i--){
		for(int j=1,k=n,mx=0;j<i;j++){
			for(;k>i&&a[i].first-a[j].first<=a[k].first-a[i].first;k--) mx=max(mx,dp[i][k]);
			dp[j][i]=max(a[i].second+a[j].second,mx+a[j].second);
			ans=max(ans,dp[j][i]);
  		}
	}
	cout<<ans;
	return 0;
}