首页IT科技Loj 507 接竹竿 题解

Loj 507 接竹竿 题解

时间2025-07-09 05:39:38分类IT科技浏览4227
导读:Loj链接:接竹竿...

Loj链接:接竹竿

$ {\scr \color {SkyBlue}{\text{Solution}}} $

题目大意:

给定一个数组            ,每次加入一种颜色的数                    ,可以取走与它颜色相同的两个数之间的所有数      ,问最后取走的所有数中最大和是多少

分析:

第一眼看到的是二分答案         ,但不知道二分的check()函数怎么写            。

没办法                    ,考虑DP(其实是因为我贪心写挂了)

DP如果可以          ,那么要至少要满足一下几个条件:

DP前面的选择情况不影响后面的选择情况(前不影响后) DP可以转移

时间            、空间复杂度等可以以后慢慢优化啦!

尝试一下?

尝试列出转移方程:

$$dp[i]=max \begin{cases} dp[i-1]& \text{$c_i$}!={c_j}\\ dp[j-1] + \sum_{k=1}^{i} v_k - \sum_{k=1}^{j-1} v_k& \text{$c_i==c_j$} \end{cases}$$

这样我们就列出了一个$O(n^3)$的DP转移方程                    。

接下来就考虑优化呗!

优化 前缀和优化

易发现      ,DP方程里有很多类似求$\sum_{i}^{j} v_k$的                   ,并且每次DP推方程时都要重新计算一遍

其实              ,求连续一段值的和   ,我们可以用前缀和优化啊!

现在方程就是$O(n^2)$的了      。

示例代码(会TLE!):

考虑进一步优化

发现转移时                  ,只能找与自己颜色相同的进行转移                 ,所以可以把每一个颜色记录下来,省下循环过程         。

这可以用链表或者$ \cal{vector}$ 实现

注意:时间复杂度此时是可以被卡到O(n^2)的!因为并没有剩下转移过程               ,只是省去了枚举无法转移情况的时间                    。

代码就不放辣QwQ!

再来看看这个转移方程:

$$dp[i]=max \begin{cases} dp[i-1]& \text{$c_i$}!={c_j}\\ dp[j-1] + \sum_{k=1}^{i} v_k - \sum_{k=1}^{j-1} v_k& \text{$c_i==c_j$} \end{cases}$$

我们可以把\cal{dp[i]}的初值赋为$\cal{dp[i-1]}$

那就只要考虑这个:

$$dp[i]=max \begin{cases} dp[j-1] + \sum_{k=1}^{i} v_k - \sum_{k=1}^{j-1} v_k& \text{$c_i==c_j$} \end{cases}$$

用前缀和优化后:

$$dp[i]=max \begin{cases} dp[j-1] + summ[i]- summ[j-1] & \text{$c_i==c_j$} \end{cases}$$

我们稍稍改变一下转移方程顺序:

$$dp[i]=max \begin{cases} summ[i]+(dp[j-1] - summ[j-1]) & \text{$c_i==c_j$} \end{cases}$$

换句话说                    ,我们只要求出与$c_i$相等颜色里   ,$dp[j-1] - summ[j-1] $ 最大值

这个可以用一个数组记下来啊!

那么只要$\cal{O(1)}$            ,就能完成转移

时间复杂度:$ \cal{O(n)}$

Code:
#include<bits/stdc++.h> #define L long long using namespace std; struct P{ int x; L y; }a[1000005]; L dp[1000005],maxx[1000005]; signed main() { int n,k; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i].x); for(int i=1;i<=k;i++) maxx[i]=-1e18; for(int i=1;i<=n;i++) scanf("%lld",&a[i].y),a[i].y+=a[i-1].y; for(int i=1;i<=n;i++) { dp[i]=max(dp[i-1],maxx[a[i].x]+a[i].y); maxx[a[i].x]=max(maxx[a[i].x],dp[i-1]-a[i-1].y); } printf("%lld",dp[n]); return 0; }
声明:本站所有文章                    ,如无特殊说明或标注      ,均为本站原创发布          。任何个人或组织         ,在未征得本站同意时                    ,禁止复制                    、盗用      、采集         、发布本站内容到任何网站                    、书籍等各类媒体平台      。如若本站内容侵犯了原著者的合法权益          ,可联系我们进行处理                   。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
解耦和耦合的概念(改进YOLOv5 | 头部解耦 | 将YOLOX解耦头添加到YOLOv5 | 涨点杀器) webpackdevserver配置项(配置Webpack Dev Server 实战操作方法步骤)