单调队列小总结
[USACO11OPEN]Mowing the Lawn G
我们根据dp方程可以找到我们所需要维护的.
我们发现 dp[j-1]-sum[j] 是我们所需要维护的 , 但是 j 是需要 i-k ~ i 显然单调队列可以排上用场:
我们对于一个 i 要去找一个 j 使得最大
#include#define int long long using namespace std; const int N=3e5+7; int n,k; int a[N]; int sum[N]; int dp[N],q[N]; int t[N]; int head,tail=1; signed main() { ios::sync_with_stdio(false); cin>>n>>k; for(int i=1;i<=n;i++) { cin>>a[i]; sum[i]=sum[i-1]+a[i]; //前缀和,方便计算j~i (即上一个断点到i的和 } //dp[i]=max{dp[j-1]-sum[j]} +sum[i] (对于j //维护dp[j-1]-sum[j] for(int i=1;i<=n;i++) { t[i]=dp[i-1]-sum[i]; // 队尾是当前值 while(head<=tail&&t[q[tail]]<t[i]) tail--;//如果左边有 比他的大的就可以出队 q[++tail]=i; //保持头是最大 while(head<=tail&&q[head] k) head++; //如方程 dp[i]=t[q[head]]+sum[i]; } cout<<dp[n]; return 0; }