这里会显示出您选择的修订版和当前版本之间的差别。
| 两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
|
2020-2021:teams:legal_string:qgjyf2001 [2020/05/06 16:05] qgjyf2001 |
2020-2021:teams:legal_string:qgjyf2001 [2020/08/07 14:26] (当前版本) qgjyf2001 |
||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | ====== dp的优化 ====== | + | [[2020-2021:teams:legal_string:front_page|back]] |
| - | ===== 一、单调队列优化 ===== | + | ====== 我太菜了 ====== |
| - | 单调队列优化,可以降低诸如$dp[i]=max\{dp[j]\}+C[i](1\le j <i)$这样的动态转移方程的时间复杂度。主要的原理就是利用一个单调队列来维护$dp[i]$的最值。 | + | ===== 专题 ===== |
| + | [[2020-2021:teams:legal_string:dp的优化]] | ||
| - | ==== 一道例题 ==== | + | [[可持久化线段树]] |
| - | [[https://www.luogu.com.cn/problem/P2627|洛谷p2627]] | + | [[DFT]] |
| - | 我们不难写出动态转移方程$dp[i]=\left\{\begin{aligned} sum[i],i\le k\\max\{dp[j-1]+sum[i]-sum[j]\}(i-k \le j\le i,i>k)\end{aligned}\right.$ | + | [[计算几何]] |
| - | 答案为$ans=max\{dp[i]\}$ | + | [[BSGS]] |
| - | 但是时间复杂度为$O(nk)$,显然会超时 | + | [[Polya定理]] |
| - | 注意到$sum[i]$可以直接提出,即$dp[i]=max\{dp[j]\}+sum[i]$,所以我们只需用一个单调队列来维护$dp[i]$的最值,复杂度可以降低为$O(n)$ | + | [[半平面交]] |
| - | 代码 | + | ===== 题解 ===== |
| - | + | [[Cf639 Div1 A、B ]] | |
| - | <code cpp> | + | |
| - | #include <stdio.h> | + | |
| - | #include <iostream> | + | |
| - | using namespace std; | + | |
| - | int n,k; | + | |
| - | long long e[100001]; | + | |
| - | long long dp[100001]; | + | |
| - | long long sum[100001]; | + | |
| - | int q[100001]; | + | |
| - | int front=0,tail=1; | + | |
| - | long long a(int now) | + | |
| - | { | + | |
| - | return dp[now-1]-sum[now]; | + | |
| - | } | + | |
| - | int main() | + | |
| - | { | + | |
| - | scanf("%d %d",&n,&k); | + | |
| - | int rec=0; | + | |
| - | for (int i=1;i<=n;i++) | + | |
| - | { | + | |
| - | scanf("%lld",&e[i]); | + | |
| - | sum[i]=sum[i-1]+e[i]; | + | |
| - | } | + | |
| - | for (int i=1;i<=n;i++) | + | |
| - | { | + | |
| - | while (front<=tail&&q[front]<i-k) | + | |
| - | front++; | + | |
| - | dp[i]=a(q[front])+sum[i]; | + | |
| - | while (front<=tail&&a(q[tail])<=a(i)) | + | |
| - | tail--; | + | |
| - | q[++tail]=i; | + | |
| - | } | + | |
| - | long long ans=0; | + | |
| - | for (int i=1;i<=n;i++) | + | |
| - | ans=max(ans,dp[i]); | + | |
| - | printf("%lld",ans); | + | |
| - | return 0; | + | |
| - | } | + | |
| - | </code> | + | |
| - | ==== 练习 ==== | + | |
| - | + | ||
| - | [[https://www.luogu.com.cn/problem/solution/P3957|洛谷p3957]] | + | |
| + | [[Cf641]] | ||
| + | [[Cf643]] | ||