洛谷P1725 琪露诺

传送门啦

本人第一个单调队列优化 $ dp $,不鼓励鼓励?

琪露诺这个题,$ dp $ 还是挺好想的对不,但是暴力 $ dp $ 的话会 $ TLE $ ,所以我们考虑用单调队列优化。

原题中说她只移动到区间 $ [i+L,i+R] $ 中的任意一格,所以我们单调队列在转移的时候 $ push $ 的应该是 $ dp[i-L] $ ,而不是 $ dp[i] $ ,对于每一段区间,我们用起点(队头)来更新答案就好了。

最后一步,因为区间的限制,我们只用在 $ [n-R+1,n] $ 中找一个最大值就好了。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 2 * 1e6;

inline int read(){
	char ch = getchar();
	int f = 1 , x = 0;
	while(ch > '9' || ch < '0'){if(ch == '-')f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
	return x * f;
}

int n,L,R,a[maxn];
int f[maxn],q[maxn],head,tail;

int main(){
	n = read(); L = read(); R = read();
	for(int i=0;i<=n;i++){
		a[i] = read();
	}
	if(L > R) swap(L , R);
	head = tail = 1; q[1] = 0;
	for(int i=L;i<=n;i++){
		while(head <= tail && i - q[head] > R)
			head++;
		while(head <= tail && f[q[tail]] <= f[i-L])
			tail--;
		q[++tail] = i - L;
		f[i] = f[q[head]] + a[i];
	}
	int ans = 0;
	for(int i=n-R+1;i<=n;i++)
		ans = max(ans , f[i]);
	printf("%d
",ans);
	return 0;
}
顺风不浪,逆风不怂。
原文地址:https://www.cnblogs.com/Stephen-F/p/9869274.html