Luogu-P2627 修剪草坪
题目
测试得分: 100
主要算法 : 单调队列优化DP
题干:
单调队列优化DP板子
分析
单调队列优化DP定长连续区间最值问题模型
代码
70分朴素DP
#include<stdio.h> #include<stdlib.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) #define LL long long #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++ #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout); using namespace std; char buf[100000],*pa,*pb; inline int read(); const int N=1e6; int n,k; LL sum[N+1],f[N+1][2]; f[i][1]代表从1-i这段区间,i这个位置的奶牛选取的效率最大值 f[i][0]代表从1-i这段区间,i这个位置的奶牛不选取的效率最大值 inline LL max(LL fa,LL fb){return fa>fb?fa:fb;} int main() { n=read(),k=read(); FORa(i,1,n) sum[i]=read(),sum[i]+=sum[i-1]; FORa(i,1,n) { f[i][0]=max(f[i-1][0],f[i-1][1]); //状态转移 FORa(j,i-k,i-1) f[i][1]=max(f[i][1],sum[i]-sum[j]+f[j][0]); } printf("%lld",max(f[n][0],f[n][1])); return 0; } inline int read() { register char c(gc);register int f(1),x(0); while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc; while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc; return x*f; }
100分单调队列优化DP
#include<stdio.h> #include<stdlib.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) #define LL long long #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++ #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout); using namespace std; char buf[100000],*pa,*pb; inline int read(); const int N=1e6; int n,k; LL sum[N+1],f[N+1][2]; int num[N+1],head=1,tail=0; inline LL max(LL fa,LL fb){return fa>fb?fa:fb;} int main() { n=read(),k=read(); FORa(i,1,n) sum[i]=read(),sum[i]+=sum[i-1]; FORa(i,1,n) { f[i][0]=max(f[i-1][0],f[i-1][1]); while(head<=tail&&f[num[tail]-1][0]-sum[num[tail]-1]<f[i-1][0]-sum[i-1]) tail--; num[++tail]=i; while(head<tail&&num[head]<i-k+1) head++; f[i][1]=f[num[head]-1][0]-sum[num[head]-1]+sum[i]; } printf("%lld",max(f[n][0],f[n][1])); return 0; } inline int read() { register char c(gc);register int f(1),x(0); while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc; while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc; return x*f; }
总结:
确定动规模型