WA 一道很好调的题 请大佬们进来看一眼
查看原帖
WA 一道很好调的题 请大佬们进来看一眼
224111
zysqh楼主2020/8/30 15:33
#include <stdio.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#define S 5000
using namespace std;
int t,Mp,W; 
int q1[S],q2[S],l1,l2,r1,r2;
inline int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch)){ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x;
}
int as[S],bs[S],ap[S],bp[S];
int ans=0;
int f[S][S];
int calc1(int i,int k){
	return f[i-W-1][k]+ap[i]*k;
}
int calc2(int i,int k){
	return f[i-W-1][k]+bp[i]*k;
}
int main() {
	t=read();Mp=read();W=read();
	as[0]=Mp;
	for(int i=1;i<=t;++i){
		ap[i]=read();bp[i]=read();as[i]=read();bs[i]=read();
	}
	memset(f,0xcf,sizeof(f));
	for(int i=0;i<=t;++i)f[i][0]=0;
	for(int i=1;i<=t;++i)for(int j=1;j<=as[i];++j)f[i][j]=-ap[i]*j;
	for(int i=1;i<=t;++i){
		for(int j=0;j<=Mp;++j)f[i][j]=max(f[i][j],f[i-1][j]);//先执行第一个转移 
		if(i>W){
			l1=1;r1=0; 
			for(int j=as[i];j<=Mp;++j){
				while(l1<=r1&&q1[l1]<j-as[i])l1++;//清除不合法的转移 
				while(l1<=r1&&calc1(i,q1[r1])<=calc1(i,j))r1--;//保证单调性 
				q1[++r1]=j;
				f[i][j]=max(f[i][j],f[i-W+1][q1[l1]]-ap[i]*(j-q1[l1]));//转移 
			}
			l2=1;r2=0;
			for(int j=Mp-bs[i];j>=0;--j){
				while(l2<=r2&&q2[l2]>j+bs[i])l2++;
				while(l2<=r2&&calc2(i,q2[r2])<=calc2(i,j))r2--;
				q2[++r2]=j;
				f[i][j]=max(f[i][j],f[i-W+1][q2[l2]]+bp[i]*(q2[l2]-j));
			}
		}
	}
	for(int i=0;i<=Mp;++i)ans=max(ans,f[t][i]);
	printf("%d\n",ans);
}
2020/8/30 15:33
加载中...