洛谷 P1714 切蛋糕(dp+RMQ)

传送门
首先,很简单的dp方程:

\[f_i=max(s_i-s_j)(j\in [i-m,i])$$然后发现$s_i$与$j$无关,可以提出来: $$f_i=s_i-min(s_j)(j\in [i-m,i])$$发现这个方程可以用数据结构优化,比如线段树,树状数组等等,我这里推荐用st表。 预处理:$O(nlogn)$ 递推:$O(n)$ 代码: ```cpp #include<bits/stdc++.h> #define ll long long using namespace std; inline int read(){ int x=0;char ch=' ';int f=1; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')f=-1,ch=getchar(); while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } int n,m; int a[500001]; int s[500001]; int st[20][500001]; inline int query(int l,int r){ int k=log(r-l+1)/log(2); return min(st[k][l],st[k][r-(1<<k)+1]); } int main(){ Log[0]=-1; for(int i=1;i<=n;i++){ Log[i]=Log[i>>1]+1; } n=read();m=read(); for(int i=1;i<=n;i++){ a[i]=read(); s[i]=s[i-1]+a[i]; st[0][i]=s[i]; } for(int k=1;k<=19;++k){ for(int i=1;i+(1<<k)-1<=n;++i){ st[k][i]=min(st[k-1][i],st[k-1][i+(1<<(k-1))]); } } int ans=-0x7fffffff; for(int i=1;i<=n;++i){ int l=i-m; if(l<0)l=0; int num=s[i]-query(l,i); ans=max(ans,num); } printf("%d",ans); return 0; } ```\]

posted @ 2017-09-26 11:24  玫葵之蝶  阅读(364)  评论(0编辑  收藏  举报