
dp
文章平均质量分 58
sophilex
Every day,Every moment
展开
-
ABC 357 G Stair-like Grid
个点无法经过,求从左上角到右下角的方案数。其中每次移动只能向右或向下。表示两点之间的所有最短路的方案数(不考虑中间是否经过障碍)表示从起点到第i个障碍,中间不经过其它障碍的方案数,还是将障碍按横纵坐标排个序,同时不妨将终点也放入。,这样就还原成了经典模型,可以直接用容斥来做。一个比较显然的思路是把原图还原为。个方块,总共有n行。中,显然排序后它会是最后一个点。但是这样做的时间复杂度是。表示S中的第i个障碍,其实是我之前写的一篇。原创 2024-06-09 16:10:42 · 1022 阅读 · 0 评论 -
【学习笔记】各类基于决策单调性的dp优化
个人认为已经非常非常全了,从入门到入土的知识点都在里面了,以及本人踩过的所有坑的(泪目原创 2023-09-16 20:00:14 · 1181 阅读 · 0 评论 -
[学习笔记]斜率优化dp 总结
我们学过不少优化类的算法了,大部分都是基于凸函数的性质给出的优化,比如Slope Trick,Wqs二分,又比如今天的斜率优化(不知道什么时候会有空把Slope Trick写掉)当dp式子满足cy−cxby−bx≤−aiby−bxcy−cx≤−ai的时候,我们要维护的是一个下凸包i原创 2023-09-02 09:27:17 · 1582 阅读 · 0 评论 -
奇怪的数位dp CF908G New Year and Original Order
然后我们看一下每一行的1的个数,其实也不难发现,第i行的1的个数=大于等于i的数字的个数,手模一下就可以验证了。所以在第d行,计数字x中>=d的数字的个数为k,则x在第d行的贡献就是(10^k-1)/9(其实就是在构造k个1)在此基础上,我们分9次来计算每一行的贡献。首先这种题目是存在一定套路的,但是没见过基本是想不出来的(估计也是其rating高的原因)所以此题的关键就是用1来组成数字,剩余的工作就都是很基础的了。求区间[L,R]内每一个数字在各数位排序后得到的数的和,答案对1e9+7取模。原创 2023-06-25 20:43:55 · 110 阅读 · 0 评论 -
一道有点仙的数位dp 方伯伯的商场之旅
为了防止越界,我们可以在一开始就判断一下,如果sum原创 2023-06-22 11:40:11 · 208 阅读 · 0 评论 -
回文串+数位dp 萌数
所以可以反过来考虑,那就是统计不含回文字串的个数,不难发现其性质就是每一位都与前两位不同。所以设一个三维的dp,i表示当前位数,j表示前一位,k表示前一位的前一位。做数位dp的话,转移就按照正常的转移来就好了,只是中间遍历时要特判一下前导0时的情况,需要将前两位都置为-1。如果正着想的话,显然所有回文串都满足有相邻两位相等或者间隔一位的两个数字相等,但是这样计数的话还要考虑到相等的位置以及第二种情况时中间数字与两边数字是否相等等一系列情况,想想也不是1e1000能解决的。原创 2023-06-18 19:43:01 · 209 阅读 · 0 评论 -
高维前缀和 学习笔记
显然一种暴力的方法就是枚举i的所有子集,考虑优化的话,我们可以尝试前缀和,因为显然如果有,我们可以将j的贡献都先算在z上面再传给i,而不必一个个来但是这样的话,就涉及到了高维的前缀和处理先来看看一维前缀和是怎么写的。原创 2023-03-25 21:29:53 · 2733 阅读 · 1 评论 -
cf851 E. Sum Over Zero
仔细观察一下,在更新的时候,其实i是固定的,变的是dp[j]-j,所以我们可以想办法找到i之前的前缀和比当前小的点的前缀最大值。那么就可以令si从小到大作为id,来维护一个前缀最大的树状数组,因为我们是按1-n的顺序更新的,所以查询的时候树状数组里的最大值就是刚好满足条件的最大值。注意一点,一开始我们的树状数组肯定初始化为-inf,但是对于一个前缀和>0的点来说,它前面没有可以更新的前缀最大值,但是它可以直接从开始算一个。可以选,dp[i]=max{dp[j]+i-j},1原创 2023-02-13 21:24:33 · 475 阅读 · 0 评论 -
AtCoder Beginner Contest 288 题解
按照一开始讲的思路,从i=l~r-k+1,以i为左端点执行一次使其值为0的操作,那么这样之后除了最后k个元素,其余元素都为0,考虑到条件为所有sum[i]都相等,一番操作之后最后k的元素也必然相等,再执行一次操作就可以了。从第二步转移到第三步的时候,我们发现,当j=i-1时,j+1>i-1,X[j+1:i-1]是非法的,所以我们直接略去这种情况,那么此时第二步展开的前半部分就等于10*dp[i-1]了,那么我们就可以O(1)转移了。对于一个遍历到的物品,我们的选择是买或者不买,以及要买的话,什么时候买。原创 2023-02-08 16:20:15 · 719 阅读 · 0 评论 -
一道(我以为是推柿子的)计数dp 牛客寒假集训 阿宁睡大觉
对于点ji的方案数)(因为每一个点的dp值都是代表其第一次被走到的方案数,不会包括其它黑点,所以这样是不会多减的),j->i的方案数用上述做法即得。显然的,把点按横坐标排序,我们设dp[i]表示走到第i个黑点且中间没有经过其它黑点的方案数,那么这样就能支撑n^2的遍历了。给定h ∗ w的矩阵,上面有n个黑点,其余的都是白点。这样就能做完这题了。原创 2023-02-04 18:26:29 · 135 阅读 · 0 评论 -
AtCoder Beginner Contest 285 题解
一周有n天,给出一个数组a,现在设计这一周的休息日的安排(至少一个),并计算每周的价值。每天的价值:休息日没价值,工作日i的价值为a[min(i1,i2)],i1表示i至少往前几天有休息日,i2表示i至少往后几天有休息日,n原创 2023-01-25 11:52:36 · 1162 阅读 · 0 评论 -
Codeforces Global Round 14 E Phoenix and Computers
看完上面之后,我其实是存疑的。为什么第一种情况可以认定每一个连通块都有左右两个位置可以放?为什么该情况下插入一格不会导致两个连通块的合并?因为如果两个连通块之间间隔为2的话,放入一个会导致合并,但第一种情况并没有与第三种情况进行去重。以及第二种情况,为什么随便找一个空插进去不会导致连通块合并而一定导致产生新的连通块?这里给出我自己的解释:我之所以会产生这样的疑问,是因为我默认这n台电脑的位置是固定的,它们就摆在那里了,第一台就是第一台,它左边一定没有别的电脑了。这很合理。但是该方法其实是假设有无数台电脑原创 2023-01-04 10:46:01 · 331 阅读 · 0 评论 -
树形dp CF461B Appleman and Tree
我们会发现一个合法状态(联通块内有且只有一个黑点)可以由两个合法状态切割而成,也可以由一个合法状态与一个非法状态(没有黑点)合并而成。所以我们可以设dp[i][j]表示以i为子树的根,满足i所在的连通块由一个黑点的方案数(dp[i][1]),和满足i所在的连通块由没有黑点的方案数(dp[i][0]).至于多个黑点的情况,则可以由该dp式分割转移。不妨先考虑dp[i]表示以i为根的子树,满足条件的删边方法数。考虑初始化:dp[i][color[i]]=1;给你一棵有 n 个节点的树,下标从 0 开始。...原创 2022-08-04 13:58:14 · 153 阅读 · 0 评论 -
四边形不等式优化区间dp
四边形不等式是一个很强有力的武器,往往可以在原本dp推导式中优化掉一个n的时间复杂度区间dp里,假如dp[i,j]和cost函数满足四边形不等式的话:dp[i][j]+dp[i+1][j+1]原创 2022-07-14 10:02:12 · 422 阅读 · 0 评论 -
AtCoder Beginner Contest 237 VP补题
E大意:给定一张无向图,两点间的边权:较高点到较低点的边权等于高度差较低点到较高点的边权等于高度差的负二倍求:图中的最大dis值思路:按题意建边即可;但是有负权,所以一般的dij不行。赛后又加强过数据,所以我跑了spfa,T烂了。。。(但是我看有一个哥们还真用spfa冲过去了。。。【崩溃】)官方题解的思路是dij考虑“势”的思想(绝):对数据进行预处理,高点到低点的边权等于0,低点到高点的距离等于高度差(>=0)那么就全是非负权边了。跑完dij后只要把数据还原回去就可以了,dis[i]=h[i]-h[1原创 2022-07-02 10:26:28 · 162 阅读 · 0 评论 -
atcoder beginner contest 230 F - Predilection
首先,如果考虑对于一个数组的任意位置进行的变换都不会相同的话,那么自己手推几次就可以发现dp[i](共i个元素的数组的变换总结果数)=dp[i-1]*2;接下来考虑两个变换可能相同的情况,那也就是中间的一段的和为0,那么这个0往左结合和往右结合的效果是一样的,那么就要减掉对应的情况数了。...原创 2022-06-12 20:48:56 · 189 阅读 · 0 评论 -
Yet Another Palindrome Partitioning
url大意:把一个字符串s分割成m个串,这m个串满足至多有一种字符出现次数为奇数次,其他均为偶数次,问m的最小值思路:一开始看错了题意,以为是可以任意重排字符串,然后刷刷敲完之后死活过不去。。。字符串顺序是不能改变的。那么这里可以用一个状压的思路。用f[i](1到26的一个01串对应的大小)来代表从1到i的每一个字母的数量(奇数为1,偶数为0)则区间[l, r]可以加一个子串,就是a[l]^a[r]的值必须为2的幂次(也就是中间只有一个奇数次数的字母)。然后用dp来对每一个状态原创 2022-05-28 21:54:30 · 135 阅读 · 0 评论 -
[序列自动机(及其应用)]求k个字符串的公共子序列数
eg大意:求三个字符串的公共子串数思路:先用序列自动机求出每一个字符串的next数组。void init(char* s,ll mas[][30]){ ll len=strlen(s+1); for(int i=len;i;--i) { for(int j=0;j<26;++j) mas[i-1][j]=mas[i][j]; mas[i-1][s[i]-'a']=i; }}假设dp【i】【j】【k】表示a串第i个字符后,b串第j个字符后,c串第k个字符原创 2022-05-25 13:53:55 · 265 阅读 · 0 评论 -
CF1336A Linova and Kingdom
看这里大意:有一个有 n 个点的树,以 1 为根,你可以选择 k 个节点,使得这 k 个节点到 1 节点的最短路径中经过的非选择的点最多。思路:简单树形dp我们肯定会优先最好的叶子结点,这个能保证中间路径最长,相同路径下选叶子节点比选非叶子节点一定是要优的。所以如果我们选了一个非叶子节点,代表它的所有儿子我们肯定都选过了,那么就得把对应的重复贡献减掉。这样一综合就得到了对应的公式:每一个点选上之后对答案的贡献应该是它的深度减去以它为根的子树的大小。这里要求每一个点的深度以及子.原创 2022-05-10 13:07:26 · 139 阅读 · 0 评论 -
CF567C Geometric Progression
看这里大意:求数组中长度为3且以k为公比的等比数列个数思路:一眼就是dp的感觉。。。但是元素范围有一丢丢大,数组肯定是开不下的,所以用map枚举中间的那个数字a,那么这个数对答案的贡献就应该是它前面的a/k的个数(前提是a%k==0)*它后面的a*k的个数这样累加即可还有一些小trick见代码:#include<bits/stdc++.h>using namespace std;#define ll long longll n,k;ll mas原创 2022-05-09 19:08:25 · 237 阅读 · 0 评论 -
求N元上升子序列(挖坑)
三元上升子序列还没搞懂,先贴着,以后填。。。大意:给定一个数组,求N元上升子序列的数量思路:(来自洛谷大佬)DP + 树状数组优化设f[i][j]f[i][j]为以a[j]a[j]为结尾的长度为ii的上升子序列的个数得到转移方程:然后用树状数组维护。。。维护啥呢,下次再说 :)...原创 2022-03-15 19:25:38 · 342 阅读 · 0 评论 -
[JSOI2008]最大数MAXNUMBER
ST表/线段树大意:m次操作1.查询后l个数当中的最大值2.上一次查询的结果加上指定数并取模加到数组的后面思路:ST表 裸的。f[i][j]查询i后面2^j个数中的最大值数组动态更新。线段树:改一下板子,把查询最后l个数的最大值改为查询【n-l+1,n】的区间最大值。注意数组开够即可。ST表code:#include<bits/stdc++.h>using namespace std;#define ll long longconst ll N原创 2022-03-04 18:29:38 · 210 阅读 · 0 评论 -
图论-分层图
分层图常见于一些有多种限制,情况比较复杂的题目中做法一般有两种第一个是运用了分层的思想,但会以dp的形式来实现,加入松弛的思想,不断更新满足条件的边权并通过SPFA或某k算法来求最短路进而得出答案。牛客 追债之旅大意:给定一张图,要在k步内从起点走到指定位置,并且每一步的时间会增加一定的权值,求最小的权值和。思路:约束条件有每一步的权值和每一条路的对应的权值以及步数的要求。可以用dp【i】【j]来表示第i天走到第j个点的最小权值和。那么对应的松弛操作就应该是.原创 2022-03-01 18:20:56 · 1034 阅读 · 1 评论 -
状压dp+小优化 炮兵阵地
没有过多可以描述的,枚举每一行的合法状态,然后一次枚举上一行,上上一行,要求状态不矛盾。可以用vector来做一个预处理,然后因为每一层都是只有满足地图条件并且不会自矛盾才能有非0的dp值,所以每一次除了枚举这一行要将当前状态与地图进行对比外,它的上一行,上上一行都不需要再与地图进行对比了。最后如果按状态开1<<10位的数组的话,三维吃不消,可以做一个小优化,打表发现合法状态也就六十几个,所以dp数组的后两维只开70也就够了,不过这样的话,dp里面就不再是对应的状态了,而是对应的状态的编号(因为原创 2021-12-24 21:52:40 · 390 阅读 · 0 评论 -
状压dp 混乱的奶牛(有点裸)
其实这个有点类似于TSP的思路,都是通过枚举当前和上一次的点来进行递推。(话说这个题的状压也许并不是那么好想?)思路:数据范围不大,应该说是异常的小,一般这种东西就应该往类似状压或者暴力的方向上去想了。dp[i][j]:状态为j且队尾为i的情况下可行的方案数 ;下一步考虑初始化:很明显应该在只放一头牛的情况下进行初始化,对于任意一头牛,它第一个放进去的时候,它就是队尾,并且此时可行数也只有1(毕竟只能放一头)原创 2021-12-23 22:39:10 · 868 阅读 · 0 评论 -
状压dp板子 德玛西亚万岁
因为数据范围这么小,答案的量又这么大,并且每一行的每一个位置都会影响下一行的决策。所以我们用01串来压缩状态。(不妨用1来代表士兵,0来代表不妨士兵)对于每一行的01串(设为st)要考虑这么几个因素:1.st当中不能有2个相邻的1,代表不存在两个左右相邻的士兵。2.st与上一行不能在同一个位置同时有1,代表不存在两个上下相邻的士兵。3.st中有1的位置,地图中对应的地方也一定是1。原创 2021-12-23 21:18:37 · 367 阅读 · 0 评论 -
TSP问题详解(旅行商问题)
对于现在走到的点i,它前面会有k给点,后面有s个点,那么与最短路有关的就是后面s给点应该如何走,而前面的k个点,我们只需记录走过这几个点所需的最短路。那么就可以用状压dp,比方说现在走到i点,01串用来代表之前走过的状态,比如n=7,i=2,01串(我们叫它st好了)是0011010,就代表2、4、5点是走过的(走过的点标1,一开始的状态就应该全是0),其中现在处在点2。那么dp[st][i]就应该表示此时在i点,状态为st时走过的最短路。...原创 2021-12-20 19:50:52 · 21353 阅读 · 2 评论 -
树形dp基础:选课
首先能发现不同的科目之间存在依赖关系,所以建树。然后题目说是没有先修课的科目会以0为根,那么就建一颗以0为根的树,向下延申。考虑dp,首先是数组的意义,不难想到用dp【i】【j】来表示以i为根,选j门课能获得的最大学分。但是这里因为我们是以0作为根的,所以最后肯定是要输出dp【0】【m】,但是0它不是一门课,所以m此时其实是加了一个1(就是m++),因为0肯定是会被选上的。或者我们就干脆直接让全体都-1,那么dp【0】【m】中的m就还是一开始的m,那么初始化时就应该是让dp【i】【0】=num【i】(n原创 2021-12-17 17:08:27 · 424 阅读 · 0 评论 -
dp优化(内存)
1.[NOIP2005]过河链接:登录—专业IT笔试面试备考平台_牛客网有些距离过大时,是可以直接去掉的,因为中间可以通过反复横跳来水距离,所以一旦发现距离过大,可以直接减少。#include<bits/stdc++.h>using namespace std;#define ll long longll l;ll s,t,m;ll mas[110];ll dp[5000100];ll dist[5000100];ll dis;bool di[5000100]={原创 2021-12-17 16:50:25 · 202 阅读 · 0 评论 -
最大子矩形
链接:登录—专业IT笔试面试备考平台_牛客网#include<bits/stdc++.h>using namespace std;#define ll long longll n,m,k;ll mas[110][4];ll dp[120][120][13];int main(){ cin>>n>>m>>k; for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ cin>原创 2021-12-08 21:11:22 · 118 阅读 · 0 评论 -
Manacher算法的基础应用:小A的回文串
其实有点合并石子那道题的味道,因为这其实也是一个类似于环状的结构,所以我们不妨将字符串翻倍,然后在0到s.size()-1的区间(闭)内,每次向右截取一段长度为s.size()的字符串,跑一遍Manacher,然后实时更新ans,最后输出ans就可以了。原创 2021-12-05 21:33:38 · 161 阅读 · 1 评论 -
二分法求最长上升子序列
贪心策略:如果两个子序列中一个的最后的一个元素的值越小那么我们越有可能在后面的遍历中给它加上其他元素用一个数组low[i]表示:长度为i的子序列的末端最小值。遍历每一个a[i]时找到一个j,如果low[j]<a[i]那么a[i]可以放在长度为j的子序列的后面,所以low[i+1]可能更新我们看low[i+1]是否比a[i]大如果low[i+1]>a[i]那么low[i+1]=a[i](显然)同时注意到,对于low的所有元素,low[j+1]>=low[j]恒成立就是说长度为j+1的子序原创 2021-12-01 16:07:11 · 1226 阅读 · 1 评论 -
dp:Music Problem
链接:登录—专业IT笔试面试备考平台_牛客网题目大意:输入n,序列包含n个整数,问是否能够找到一个子序列的和为3600的整数倍题目数据可以达到1e9,这是远超3600的,事实上我们也无需真的去开一个1e9的数组来存放这些数据,因为要求的只是能否使和成为3600的倍数,所以我们只需关注它们与3600的余数即可。另外,当n>3600的时候,前3600个数的和就一定是3600的倍数,就一定可以,所以我们在这种情况下就无需判断了。那么在n<3600时,具体要怎么操作呢?我们可..原创 2021-12-01 08:34:25 · 126 阅读 · 1 评论 -
dp:失衡天平
链接:登录—专业IT笔试面试备考平台_牛客网首先不难发现,对于任意次操作,其都可以在一次操作内完成,只不过需要改变一下左右顺序之类的东西而已。所以我们可以建立一个dp数组[i][j],表示前i的物品,在差值为j的情况下能取到的最大重量。(注意这里是要求把j塞满的,所以其跟普通dp是不太一样的,我们应该要将数组初始化为-0x3f,而不是0.)然后,对于每一个物品,我们有三种选择:1.不放进天平,dp[i][j]=dp[i-1][j];2.放进较重的天平,dp[i][j]=dp[i-1][j原创 2021-11-28 10:14:31 · 349 阅读 · 0 评论 -
dp:maximum sum,求数组不相交子区间的最大元素和
一个方法是,用两个dp数组来维护两个区间的最大元素和,为了保证不相交,我们可以让a【i】求以mas【i】为终点的最大区间和,b【i】求以mas【i】为起点的最大区间和,然后一次循环求出最大的a【i】并加上其下一个b【i】即可;原创 2021-11-24 17:09:08 · 233 阅读 · 0 评论