02 2020 档案
摘要:分析:本题是一道状压dp的经典题目,我相信很多人都做过最短哈密顿路径,只要做过那道题,这道题就迎刃而解。我们自然想到可以用f[i][j]表示当前已经吃过i,这次吃的是j来表示状态,注意i是用二进制表示的,每个食物都对应一个位置因此我们就能用除去j且包含k的集合来更新这个状态。因为题目说如果k在j前面
阅读全文
摘要:本题可以用并查集求同构的原因是,每个点只能和两个点相连,因此只有环和链两种情况,没有其他的种类。 首先我们知道同构就是有相同个数长度的的链和相同个数长度的环。这样我们在并查集只需要维护两个信息。 一个是集合大小,一个是有没有环。因为环只可能在头尾节点,所以只需要把环记录在我们并查集的根节点就行了。就
阅读全文
摘要:经典容斥原理,这其实是离散数学解不定方程或者高中组合数学的隔板法。 原问题可以转换为 x1+x2+x3+...xn=M+N; 又因为每个都有限制需要<=a[i],因此我们可以反向考虑,总数-不合法数 而不合法数是所有>a[i]的合集,因此可以用容斥原理拆分,这里可以用二进制的表示方法表示取哪几个。
阅读全文
摘要:本题是并查集删点的经典例题,并查集删点操作的核心就是虚点,利用res数组映射新点,这样就不会对原来的内容造成干扰。 例如 1,2,3,4 ,这些点再普通操作下变成一个集合,根节点是4。 那么如果我们要删除4,我们考虑将4映射到5上,值得一提的是,不是直接把p[4]=5 而是我们在刚开始就设置一个re
阅读全文
摘要:首先提取题目信息,我们需要计算朋友的关系,以及计算不开心值。 其实看题目我们很容易就有并查集的感觉,之后我们要去验证这个算法是正确的 题目要求的是求不开心值,那么我们就可以想到使用并查集求集合总数就可以了 虽然朋友不存在传递性,但是这并不影响不开心值的大小,因为如果a和b是朋友,b和c是朋友 那么虽
阅读全文
摘要:本题从题目给出的条件我们发现了最小生成树的影子,也就是kruscal的影子 其实我们在写kruscal的时候就是利用并查集的思想来写的 这题需要注意的是,我们在求取的过程中l并不需要减少,我们只要最小生成树中的最大边权小于等于l就行了 这就让我们想到了可以从小到大对边权排序,之后枚举维护树集合,如果
阅读全文
摘要:分析: 本题最重要的是通过向量的想法来解决这一类关系,这样思维难度大大降低,首先我们明白一点 根据传递性的定义(也就是离散数学中的传递性),x->y =x->z+z>y 我们要知道的一点是,并查集中的题目都是有传递性的,而传递性的题目并不一定能通过并查集解决 我们知道我们要将两个不同的集合合并,就是
阅读全文
摘要:这道理重要的想法就是利用并查集缩点,将所有相等的点缩成同一个点 因为如果不缩点,那么如果两个数相等,其他的数与他们中任意一个数有关系,就需要把相等的数的关系也都连上,也就是加边。这样十分复杂 我们又可以发现,如果缩点,因为每个点本身有rp值,所以缩成的点能排序的话,原先也可以。就是基于这个原理证明的
阅读全文
摘要:本题一个很巧妙的设计就是dp状态,设计为f[l][r][i][j],从l-r,左右端点是哪个 这样就可以通过递归来计算小区间的值 记住,要先进行字符串的匹配,也就是常规的括号进出栈问题,记录下来每个左括号匹配的右括号的位置 网上有些记录了右括号的匹配左括号是谁,其实没有必要,因为用不大,大概是因为第
阅读全文
摘要:这题相当的精彩,写完这个对码力和思维都有很大的提升。 题目的意思是stan先画竖线,oll画横线且过stan的一个点,stan先画,因为两个人都想赢,oll后画,所以oll肯定会在stan的基础上找最大的,那么stan所求的自然是最小的情况,因为总点数是固定的 但是stan也想赢,所以他可以决定竖线
阅读全文
摘要:这题用容斥定理做会代码简单不少,但是一个是我数学不好,另一个我感觉这就是个扫描线模板题 首先也是求面积并,但是本题不是所有的矩形都用得到,我们根据题目的询问来用vis存储用得到的矩形 注意,因为我们已经离散化了,所以当前的矩形不是原先的矩形排序,而询问的时候是告诉我们原先矩形的位置,所以我们在输入的
阅读全文
摘要:网上很多区间dp的代码是记忆化搜索的,还有些说这种区间dp必须倒序枚举 其实没有必要倒序,我们只需要按正常的区间dp的定义,第一维是长度,第二维枚举起点,第三维枚举断点即可 判断凸包的方法就是跟网上一样的常用方法Graham #include <iostream> #include <cstdio>
阅读全文
摘要:本题求周长,其实思路与面积完全相似 离散化+扫描线,本题甚至可以不用离散化,因为数据范围并不是特别大 我们能想到的暴力就是先算一遍横的,再算一遍竖的,我不知道这样能不能过,或许可以 但是我们发现其实可以在求竖线的时候顺便把横线求了,因为一条横线的长度永远是相邻x的差值 我们只需要考虑两个相邻的x有几
阅读全文
摘要:这道题我们发现如果从前面往后插,我们并不能得到正确答案,因为位置一直在变化, 所以我们考虑从后往前插,最后一个数的位置肯定是正确的,接下来的树根据这个数的位置而改变 这里用到了一个权值线段树的一些想法,根据节点的大小来选择插哪边 #include<iostream> #include<cstdio>
阅读全文
摘要:本题和某一年的oi题非常相似,都是经典套路 我们知道我们在送完食物后既可以向前送也可以回头送,这就体现了区间dp的思想 为什么我们这次的区间dp不用枚举第三维k来枚举从哪里送过来呢? 因为送货员不是傻子,他如果送到你这了,那么在你们两之间的可以都顺路送了,所以我们只需要枚举两个位置就行 这题的输入不
阅读全文
摘要:对于这道题,我发现好多网上的题解对dp的物理意义讲的并不是十分透彻,但是代码又是正确的,这样初学者会感到十分难以接收dp的正确性 在这篇题解,我会讲解我的dp方程的物理意义(其实是对网上代码的理解之后的自己的想法),这题我觉得思维难度还是挺大的,如果是第一次做的话 首先我们看到什么改变字符串,又是最
阅读全文
摘要:动态规划要从最优子结构来推出大的方案 对于本题,我们要思考,什么是大的,什么是小的。 或许有些人会想设计状态为f[i],表示我从1-i的最小花费,但是仅仅这样是不够的,因为在这之间进小黑屋的不一定要在这之间就出来,他有后效性 那么什么是没有后效性的呢,如果我们判定这个区间就是全部的大小,他没有后面还
阅读全文
摘要:这题一看就跟石子合并的类型相似,但是我们对状态的定义需要略加改变 因为我们观察到头和尾是不能删除的 我们定义f[l][r]为不删除头尾的情况下的最小值 这样我们就能枚举最后一次删的是哪个点了 #include<iostream> #include<algorithm> #include<cstdio
阅读全文
摘要:我们知道一个的是0,因此先初始化两个长度的时候 之后运用区间dp的思想,如果s[l]和s[r]满足是一对,那么先由内部更新 之后我们枚举断点,计算相加的情况 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath>
阅读全文
摘要:本题是一个思维题,我们想到,如果一个边左右两侧的点都超过k个,那么他就可以用交集,不然的话就没有交集,因为会有一遍没法k个 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector>
阅读全文
摘要:本题最关键的就是dfs序,这跟之前有一道求父节点中的节点个数很像,我们对这个树进行dfs,记录他开始的节点和最终的节点,这样只要在两个点之间做dfs就行了 首先这不会破坏树的结构,其次,他还表示了每个节点间的相对关系,这是一种很常见的树状数组的技巧 本篇代码需要用c++交,如果想用g++,需要把ve
阅读全文
摘要:本题原理和代码讲解会在近日放到b站,对题目解法不是很了解的同学可以关注b站 朝暮不思 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<string> #
阅读全文
摘要:根据武森的国家集训队论文我们知道,只需要在四个点插入值即可,之后用二维数组求和,因为矩阵上都是0和1,并且初始为0,我们只需计算他更改次数的奇偶次 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #inc
阅读全文
摘要:#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<string> #include<cstring> #include<map> #include<set
阅读全文
摘要:斜率dp的做法很单一,只要看出乘法就可以做,并且本题所以数据都是正数,所以可以做成线性复杂度 注意的是,我们在初始化队头的时候,要插入x-1的位置,因为更新的起点不能比第二维的要小 #include<iostream> #include<algorithm> #include<cstdio> #in
阅读全文
摘要:2019杭电多校第六场的一道签到题 这次我们显然要求的二维矩阵的最大值,分析题目我们可以得到几个细节。 1.首先数据很大,肯定要离散化。 2.离散化后,我们想象有很多点在一个平面内,要统计矩阵最大值 3.我们之前接触过如何求一条线上的最大子段和,只要用线段树维护四个值就能够解决 4.根据已知,我们发
阅读全文
摘要:A题 签到题,只要从头枚举即可,注意如果AB中的字符相等,那么C也要和他们相等,因为C每次都要和一个进行兑换 #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> usin
阅读全文
摘要:本题我们首先很容易可以列出朴素的状态和转移方程 f[i][j],代表前i个分j次购买的最小值 那么显然,这个值可以根据j-1次的所有结果更新而来,但这样的算法是n^2的,不过这题数据范围好像不太大 因为我是专题训练,所以我直接用上了斜率优化的方法 因为题目的转移方程是 f[i][x]=min(f[j
阅读全文
摘要:网上很多人说这是一道线段树水题,但是我却错了一晚上,下面我来分析一下这道题做的时候会遇到的困惑 如果看到了这篇题解,我相信你已经看到其他题解中离散化的正确方法,这也是本题中最难的一个地方 但是我发现网上的题解并没有详细讲述为什么这样就能防止错误情况,对于初学者来说或许难以理解原理 1.首先为什么只有
阅读全文
摘要:一道经典的树状数组老题,从题目中我们看出要求五元递增组,而普通树状数组只能求二元,我们我们考虑开五维树状数组来求取 例如 tr[3][x],就代表以x为结尾的三元递增组 for(i=1;i<=n;i++){ int pos=find(a[i]); add(1,pos,1); for(int j=2;
阅读全文
摘要:这道题目简直是一道阅读理解题,我看了半天没看懂问什么,后来靠翻译看懂了,我来把他翻译一下 现在有M个物品,每个物品费用为p[i],体积为w[i],可以有low[i]-up[i]个物品可以取,假设你取table[i]个物品,问你当满足所有w[i]*t[i]的和为0的情况下,怎么取能使p[i]*tabl
阅读全文
摘要:#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<string> using namespace std; const int N=1e4+10; int a[N]; int root;
阅读全文
摘要:fhq-Treap是一种非常优秀的无旋平衡树。下面我们来介绍他的函数原理 我们先介绍他的两个重要函数 1.spilt(分割函数) 我们将整棵树按照值的大小分割成x,y两棵树,x中的值都是小于等于key值的 这样我们就可以通过递归操作来解析,下面看具体代码 void spilt(int p,int k
阅读全文
摘要:2000分的构造题果然超过了我的能力范围,我太菜了 本题的思路是这样的,我们用vector存储父子节点的关系 我们首先递归到子节点,先对子节点求一个答案vector,假如子节点求好了后,我们只需要把父节点插到对应的c值即可 比如c是3,我们就把父节点插到由子节点组成的vector的第四个位置,这样我
阅读全文
摘要:最近我发现cf上出现很多状态机模型,然而这种模型是dp中最容易理解也是最有套路的一点 本题能用这种方法做的原因是数值都是大于0的,就不可能存在先走上去再走下来的情况,我刚开始误认为有这种情况导致无法下手 我们显然可以定义f[i][j]表示用j工具到达i层的最小值,因此j有两个选项,如果对于本题一开始
阅读全文
摘要:本题可以看出是算number的个数,重点是转化父子节点的关系,我们可以通过dfs来获得前面需要的节点 注意的是,这个点加完计算后,一定要删除,不然会影响兄弟节点的计算 #include<iostream> #include<cstdio> #include<cmath> #include<cstri
阅读全文
摘要:这题我们发现其实是dp的状态机模型,虽然我们发现一个数字可以更改多次 但是我们只要求相邻的不同,所以一个数字最多只跳两次,因为这样就能保证相邻不同,越多没有意义且费钱 所以我们只需三个for循环就能转移 另外本题有几个注意点 1.数据范围很大,所以不能用cin 2.memset会超时,血的教训,在大
阅读全文
摘要:#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<map> #include<vector> using namespace std; typedef
阅读全文
摘要:本题重要的一个操作就是撤销之前的操作,并且可以撤销已经撤销的操作 所以我们可以使用主席树这种数据结构来维护,如果撤销,就是将当前版本指向指定位置的版本 这题其实没有建树的必要,但是我习惯建树,我们需要一个len数组和一个pos变量记录有多少个版本以及如果插入应该在哪个位置插入,这样只需线段树就能解决
阅读全文
摘要:一道很老的斜率优化dp 斜率优化看上去很难,其实是有技巧的 。 对于dp题目,如果你想优化他,一定要先列出朴素的表达式并观察性质 对于本题我们可以发现,如果要更新dp[i],我们就要从前面找到dp[j]+(s[i]-s[j])^2+m的最小值,其中s是前缀和 我们就可以猜测,一定有很多不可能转移的内
阅读全文
摘要:本题的做法是斜率优化dp,但是这题杭电经过数据加强后即使算法正确也很难通过 必须要用读入加速,但这个其实在acm中并不要求,所以不建议做,同题可做poj 2018 #include<iostream> #include<algorithm> #include<cstdio> #include<cma
阅读全文
摘要:首先我们可以推出朴素的dp转移方程 dp[i]=min(dp[j])+max(a[j+1]...a[i]) 但是这个转移方程显然是超时的,所以我们需要对转移方程进行优化 做这种题目的时候,我们需要对方程进行观察,我们发现,我们需要保存两种值,一个是前面已经算过的dp方程,这个很简单 另一个是一段满足
阅读全文
摘要:因为上方和右上方都要打掉才能打这个位置,所以从第一行往下枚举不能获得正确答案,因此考虑倒序枚举,从最后一列按行枚举 具体注释看代码 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vec
阅读全文
摘要:根据对题目的观察,我们可以发现本题其实可以抽象成正序对和逆序对的个数的题目 这就能让我们联想到使用树状数组来解决问题 另外本题需要离散化,因为数据过大。 我们可以先求取所有情况,减去不合法的情况,也就是所谓的容斥原理,那么那些是不满足的呢? 我们从题目看出他要是四元组,而我们用乘法原理求出的情况,包
阅读全文
摘要:区间k小数是主席树的模板题目,如果区间不包含,用莫队+权值线段树也能解 主席树是可持久化线段树,所为可持久化,就是每次只新增不一样的节点,而保留前面的版本,这样可以做到查询。 如果询问时1-r,那么直接主席树,询问的是l-r,就用到前缀和思想,具体看代码注释 #include<iostream> #
阅读全文
摘要:A题 我们注意到如果存在两个奇数,那么就能满足题目条件,所以我们就从头寻找两个奇数,没有的话就是无解 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<s
阅读全文
摘要:本题是可持久化0-1 trie树的题目 做这题我相信都已经学会可持久化trie树的基本方法,所以本文不过多解释原理 在下面代码中有很多注释,介绍了写法。 可持久化trie树的重点就是他只在原有基础上新增了添加的内容,而保留前面的,所以用到了很多复制的操作 01trie树当中,假如该位置为1,那么我们
阅读全文
摘要:A题 本题根据题意模拟能解,不排除更好的做法 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #include<cstring> using namespace std;
阅读全文
摘要:本题可以使用权值线段树+离散化+二分解答 首先观察题目,题目要求i-j区间之内的第k大的树 所以我们可以用权值线段树,但是权值线段树只能在查找全局最大值,本题要求i-j区间的最大值 所以我们考虑使用莫队算法,因为这道题我们看出可以离线查询,对每个询问进行查询记录 另外这题数据大,所以使用离散化,具体
阅读全文
摘要:A题 肯定是1越多越好,因为位数越大越大,所以当n是2的倍数的时候,全是1 但是n可能不是n的倍数,此时应该有(n-3)/2个1和1个7,并且7在前面 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #i
阅读全文

浙公网安备 33010602011771号