洛谷 P10119 『STA - R4』踱步

题目来源于:洛谷

题目本质:动态规划及优化,单调队列

题目思路:

设 fi,k,op​ 表示对于前 i 个位置,强制在 i+1 分钟初踱步,总共踱步 k 次,且第 i 分钟在屋内(op=0)或屋外(op=1)的最大答案。

显然我们有以下转移方程:

fi,k,op​=j=k−1maxi−1​fj,k−1,1−op​+si,op​−sj,op​+[i−j≤T]P

移项可得:

fi,k,op​−si,op​=j=k−1maxi−1​fj,k−1,1−op​−sj,op​+[i−j≤T]P

滚动数组滚掉一维:

gi,op​−si,op​=j=k−1maxi−1​fj,1−op​−sj,op​+[i−j≤T]P

完整代码如下:

#include<bits/stdc++.h>
#define int long long
#define N 200010
using namespace std;
int id,T,n,m,t,p;
int f[N][2],s[N][2],g[N][2],q[N];
int get(int x,int y){return f[x][y^1]-s[x][y];}
void work(int pos,int op){
	int now=-1e18;
	int l=1,r=1;
	q[1]=pos-1;
	for(int i=pos;i<=n;i++){
		if(i-t-1>=pos-1){
			now=max(now,get(i-t-1,op));
		}
		while(l<=r&&q[l]<i-t){
			l++;
		}
		g[i][op]=max(now,get(q[l],op)+p)+s[i][op];
		while(l<=r&&get(i,op)>=get(q[r],op)){
			r--;
		}
		q[++r]=i;
	}
} 
signed main(){
	cin>>id>>T;
	while(T--){
		cin>>n>>m>>t>>p;
		for(int i=1;i<=n;i++){
			cin>>s[i][0]>>s[i][1];
			s[i][0]+=s[i-1][0];
			s[i][1]+=s[i-1][1];
			f[i][0]=s[i][0];
			f[i][1]=s[i][1];
		} 
		int ans=max(s[n][0],s[n][1]);
		for(int i=1;i<n;i++) ans=max(ans,max(f[i][0]+s[n][1]-s[i][1],f[i][1]+s[n][0]-s[i][0]));//一次踱步
		for(int pos=2;pos<=m;pos++){
			work(pos,0),work(pos,1);
			for(int i=pos;i<n;i++){
				f[i][0]=g[i][0];
				f[i][1]=g[i][1];
				ans=max(ans,max(f[i][0]+s[n][1]-s[i][1],f[i][1]+s[n][0]-s[i][0]));
			} 
		}
		cout<<ans<<endl;
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值