Loj 507 接竹竿 题解
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!):
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]=dp[i-1];
for(int j=1;j<i;j++)
if(a[i].x==a[j].x) dp[i]=max(dp[i],dp[j-1]+a[i].y-a[j-1].y);
}
考虑进一步优化
发现转移时,只能找与自己颜色相同的进行转移,所以可以把每一个颜色记录下来,省下循环过程。
这可以用链表或者$ \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;
}
Loj 507 接竹竿 题解的更多相关文章
- 洛谷 P4248 / loj 2377 [AHOI2013] 差异 题解【后缀自动机】【树形DP】
可能是一个 SAM 常用技巧?感觉 SAM 的基础题好多啊.. 题目描述 给定一个长度为 \(n\) 的字符串 \(S\) ,令 \(T_i\) 表示它从第 \(i\) 个字符开始的后缀,求: \[ ...
- 洛谷 P3975 / loj 2102 [TJOI2015] 弦论 题解【后缀自动机】【拓扑排序】
后缀自动机入门. 题目描述 为了提高智商,ZJY 开始学习弦论. 这一天,她在<String theory>中看到了这样一道问题:对于一个给定的长度为 \(n\) 的字符串,求出它的第 \ ...
- LOJ P10008 家庭作业 题解
每日一题 day45 打卡 Analysis 这道题跟LOJ P10004 一样,但是数据范围不同,不允许O(n²) 的贪心算法通过. 我们可以加一个limit 来判断这个截止期限已经不行了,所以以后 ...
- LOJ P10022 埃及分数 题解
每日一题 day62 打卡 Analysis 这道题一看感觉很像搜索,但是每次枚举x∈(1,10000000)作为分母显然太蠢了. 所以我们要想办法优化代码. 优化一:迭代加深 优化二: 我们确定了搜 ...
- LOJ P10118 打鼹鼠 题解
每日一题 day17 打卡 Analysis 二维树状数组的单点修改和区间查询,和一维的差不多 #include<iostream> #include<cstdio> #inc ...
- LOJ P10117 简单题 题解
每日一题 day15 打卡 Analysis 树状数组 用树状数组来维护每个字符变化的次数,如果是偶数就是0,奇数就是1 #include<iostream> #include<cs ...
- LOJ P10116 清点人数 题解
每日一题 day13 打卡 Analysis 用简单的树状数组维护单点修改和查询就行了 #include<iostream> #include<cstdio> #include ...
- LOJ P10150 括号配对 题解
Analysis 区间dp裸题 初始化有点麻烦 i,j能匹配时要特判 #include<iostream> #include<cstdio> #include<cstri ...
- LOJ P10148 能量项链 题解
Analysis 区间dp裸题,因为是环所以存两次 #include<iostream> #include<cstdio> #include<cstring> #i ...
- LOJ P10147 石子合并 题解
Analysis 区间dp+前缀和 #include<iostream> #include<cstdio> #include<cstring> #include&l ...
随机推荐
- python关于Django搭建简单博客项目(详解一)
上一篇我们说了如何搭建简易博客网站,下面我们来进行详细解答.本文没有特定顺序,请结合上一篇和源代码参照学习. 相关源代码和解析请参看:https://github.com/Cheng0829/mysi ...
- win10+ubuntu双系统的坑
1.把U盘里\EFI\BOOT\grubx64.efi文件重命名为mmx64.efi,避免系统提示缺少文件而退出安装: 2.如果电脑显卡为N卡,则在install Ubuntu时,按e进入编辑,在qu ...
- FileNotFoundError: Could not find module libmxnet.dll
解决方法:把CUDA的bin目录下的dll文件全部复制到libmxnet.dll所在的目录 问题原因:libmxnet.dll引用了一些CUDA的dll,但是找不到路径.
- 栈溢出漏洞利用流程——以syncbrs为例
0x1 缓冲区溢出漏洞攻击简介 缓冲区溢出攻击是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序的堆栈,使程序转而执行其他指令,以达到攻击 ...
- 快速创建软件安装包-ClickOnce
大家好,我是沙漠尽头的狼. .NET是免费,跨平台,开源,用于构建所有应用的开发人员平台. 今天介绍使用ClickOnce制作软件安装包,首先我们先了解什么是ClickOne. 1. 什么是Click ...
- Git创建、diff代码、回退版本、撤回代码,学废了吗
.eye-care { background-color: rgba(199, 237, 204, 1); padding: 10px } .head-box { display: flex } .t ...
- python基础(三)装饰器
字典推导式: data_list = ['1 hello','2 world'] result = {item.split(" ")[0]: item.split(" & ...
- 2、两个乒乓球队,甲队有a,b,c三名队员,乙队有d,e,f三名队员,甲队a不愿和d比赛,c不愿意和d,f比赛,求合适的赛手名单
/*两个乒乓球队,甲队有a,b,c三名队员,乙队有d,e,f三名队员,甲队a不愿和d比赛,c不愿意和d,f比赛,求合适的赛手名单 */ #include <stdio.h> #includ ...
- 基于python的数学建模---非线性规划
凸函数的非线性规划 minimize 求解的是局部最优解 简单的函数,无所谓 复杂的函数 初始值的设定很重要 scipy.optimize.minimize(fun,x0,args=(),method ...
- Crane如何做到利用率提升3倍稳定性还不受损?
作为云平台用户,我们都希望购买的服务器物尽其用,能够达到最大利用率.然而要达到理论上的节点负载目标是很的,计算节点总是存在一些装箱碎片和低负载导致的闲置资源.下图展示了某个生产系统的CPU资源现状,从 ...