求序列中长度不超过m的最大连续子序列的和

    1. for (int i = 1; i <= n; i++) {
    2. scanf("%d", &a[i]);
    3. s[i] = s[i-1]+a[i];
    4. }
    5. q.push_back(0);
    6. for (int i = 1; i <= n; i++) {
    7. while (q.size() && q.front()<i-m)
    8. q.pop_front();
    9. ans = max(ans, s[i]-s[q.front()]);
    10. while (q.size() && s[q.back()]>=s[i])
    11. q.pop_back();
    12. q.push_back(i);
    13. }
    14. cout << ans << "\n";

    在一个序列中找若干段子序列,每一段长度不能超过k,求能满足条件的最大点权和

    1. //f[i]表示从前i个元素中选的最大合法方案数
    2. //状态转移方程f[i] = max(f[i-1], f[i-j+1]+s[i]-s[i-j]) = max(f[i-1],g[i-j]+s[i]); (1<=j<=k)
    3. //定义一个单调递减的队列维护g[i-j]使队头最大,由1<=j<=k可知要求的是长度为k的滑动窗口的最大值。
    4. int g(int i) {
    5. if (!i)
    6. return 0;
    7. return f[i-1]-s[i];
    8. }
    9. cin >> n >> k;
    10. for (int i = 1; i <= n; i++) {
    11. scanf("%d", &a[i]);
    12. s[i] = s[i-1]+a[i];
    13. }
    14. deque<int> q;
    15. q.push_back(0);
    16. for (int i = 1; i <= n; i++) {
    17. while (q.size() && q.front()<i-k)
    18. q.pop_front();
    19. f[i] = max(f[i-1], g(q.front())+s[i]);
    20. while (q.size() && g(q.back())<=g(i))
    21. q.pop_back();
    22. q.push_back(i);
    23. }
    24. cout << f[n] << "\n";

    在一个序列中找若干个点,任意相邻两点间距离不能大于k,求能满足条件的最小点权和

    1. //f[i]表示在前i个点中选第i个点的小合法方案数
    2. //状态转移方程f[i] = min(f[j])+w[i]; (i-k<=j<=i-1)
    3. //定义一个单调递增队列维护f[j]使队头最小
    4. cin >> n >> k;
    5. for (int i = 1; i <= n; i++)
    6. scanf("%d", &a[i]);
    7. deque<int> q;
    8. q.push_back(0);
    9. for (int i = 1; i <= n; i++) {
    10. if (q.front() < i-k)
    11. q.pop_front();
    12. f[i] = f[q.front()]+a[i];
    13. while (q.size() && f[q.back()] >= f[i])
    14. q.pop_back();
    15. q.push_back(i);
    16. }
    17. int ans = 0x3f3f3f3f;
    18. for (int i = n-k+1; i <= n; i++)
    19. ans = min(ans, f[i]);
    20. cout << ans << "\n";

    二维滑动窗口(求大矩阵中固定小矩阵中的最值)

    1. int n, m, k;
    2. int g[N][N];
    3. int row_min[N][N], row_max[N][N];
    4. void get_min(int a[], int b[], int tot) {
    5. deque<int> q;
    6. q.push_back(0);
    7. for (int i = 1; i <= tot; i++) {
    8. if (q.size() && q.front()<=i-k)
    9. q.pop_front();
    10. while (q.size() && a[q.back()]>=a[i])
    11. q.pop_back();
    12. q.push_back(i);
    13. b[i] = a[q.front()];
    14. }
    15. }
    16. void get_max(int a[], int b[], int tot) {
    17. deque<int> q;
    18. q.push_back(0);
    19. for (int i = 1; i <= tot; i++) {
    20. if (q.size() && q.front()<=i-k)
    21. q.pop_front();
    22. while (q.size() && a[q.back()]<=a[i])
    23. q.pop_back();
    24. q.push_back(i);
    25. b[i] = a[q.front()];
    26. }
    27. }
    28. int main() {
    29. cin >> n >> m >> k;
    30. for (int i = 1; i <= n; i++)
    31. for (int j = 1; j <= m; j++)
    32. scanf("%d", &g[i][j]);
    33. for (int i = 1; i <= n; i++) {
    34. get_min(g[i], row_min[i], m);
    35. get_max(g[i], row_max[i], m);
    36. }
    37. int ans = INF;
    38. int a[N], b[N], c[N];
    39. for (int i = k; i <= m; i++) {
    40. for (int j = 1; j <= n; j++)
    41. a[j] = row_min[j][i];
    42. get_min(a, b, n);
    43. for (int j = 1; j <= n; j++)
    44. a[j] = row_max[j][i];
    45. get_max(a, c, n);
    46. for (int j = k; j <= n; j++)
    47. ans = min(ans, c[j]-b[j]);
    48. }
    49. cout << ans << "\n";
    50. return 0;
    51. }