10 2021 档案
摘要:传送门 传送门 判断节点u的子树是否是对称二叉树的方法: 判断hash1[l[u]]是否等于hash2[r[u]]。 其中hash1中存的是按照根左右的顺序的哈希值,hash2存的是按照根右左顺序的哈希值。 当两个hash值相等时,即为对称二叉树。 单哈希和双哈希貌似都不太稳定,而用自然溢出即可AC
阅读全文
摘要:传送门 解题思路 关键点:根据线性基的性质,若序列数字个数大于等于30,则一定有异或值为0的两个集合。 所以对于每个询问,先判断两个点之间的路径长度是否大于等于30,若小于30,直接暴力找,线性基判断,否则直接判断。 对于每次修改,可以用线段树维护树剖。 AC代码 #include<iostream
阅读全文
摘要:传送门 解题思路 首先背过线性基的一个性质吧(因为我不会证明): 线性基里的每一个异或值出现的次数相等,为 。 然后这题就变成统计某个数是第几大异或值了。 分类讨论在归纳一下: 假设询问的数字是q。当处理到第i位且q的这一位为1,且线性基这一位有数,则 当前面位异或起来得到的
阅读全文
摘要:传送门 前置知识: Nim博弈 线性基 解题思路 注意两人各进行一次操作,所以目的就是要使对方不管怎么拿,都不能到达一个异或和为0的状态。 所以相当于第一次操作结束后,必须保证任意元素异或值不为0。 这就很典型的线性基了,并且和[BJWC2011]元素这个题完全一样,贪心取即可。 AC代码 #inc
阅读全文
摘要:传送门 解题思路 非常清新的一道题。 先假设选择了一条1->n的主路径,然后在这条路径上向外拓展。 发现只有环对答案有影响,因为非环的边一定会走两次,异或和为0。 因为图是联通的,所以可以经过任意环,所以可以把所有的环的异或值扔到线性基里。 然后再考虑选择哪一条路径,我们发现若1->n有多条路径,其
阅读全文
摘要:传送门 解题思路 贪心策略:按照价值从大到小排序,能选就选。 用线性基维护是否发生冲突。 正确性:异或和为0的几个数中去掉价值最低的异或和一定不为0。 AC代码 #include<iostream> #include<algorithm> #include<cmath> #include<cstdi
阅读全文
摘要:线性基 推荐Menci博客的前半部分:https://oi.men.ci/linear-basis-notes/ 非常学术的讲解了线性基。 然后对于如何构造线性基,我一般使用以下方法: 对于每一个加进来的数,从高位向低位扫,若某一位是1,则看线性基的a[i]是否有值,若有,则这个数^=a[i],否则
阅读全文
摘要:传送门 解题思路 关键:根据定义,线性基是线性无关的,2的线性基内的元素数量次幂即为可能的异或数量。 于是就成了板子题了。 AC代码 #include<iostream> #include<algorithm> #include<cmath> #include<cstdio> #include<cs
阅读全文
摘要:传送门 解题思路 简要来说就是求每一个基环树的直径的和。 想起来很好想,就是把环上每个节点挂的子树的深度的信息挂到环上的节点上,然后断环为链,找一段最大的区间使得dep[a]+dep[b]+dis[a,b] 最大,dis[a,b] 又可以用前缀和预处理成 dis[b]-dis[a],于是式子变成了d
阅读全文
摘要:传送门 解题思路 和上一题很像,不过这是个基环森林。 还是一样要注意是否是二元环(可以通过删边和反向边来处理)。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath
阅读全文
摘要:传送门 解题思路 先找到基环树上的环,然后断掉任意一条环上的边,分别以两个端点做树形dp(没有上司的舞会),最后答案就是max(dp1[s][0],dp2[t][0])。 其中dp1[s][0]为以s为根节点不选s的答案,dp2[t][0]表示以t为根节点不选t时的答案。 注意断边不能只看点,因为有
阅读全文
摘要:传送门 基环树 定义: n个节点n条边的连通图。 性质: 很显然有且仅有一个环。 如何找环: dfs,每次读到一个节点入栈(类似Tarjan) 拓扑排序:最后剩下的度数不为零的点一定就在环上 题目通常解法: 把环看做一个整个树的根,然后把子树的信息挂到环的每一个点上,问题变成了环上操作,再根据题目需
阅读全文
摘要:Day 0 晚上自己一个人住在宾馆,不过能和xhy、ljx、gjy他们联系上还是蛮不错的啦。 Day1 上午 早上很早就起床了,收拾收拾行李,然后拖着行李箱“长途跋涉”,穿过一片茂密的树林,来到汹涌的河流面前,于是跨过银白色的状元桥,走上一条蜿蜒起伏的羊肠小道,最后踏过一个古老神秘的大门,抵达目的地
阅读全文
摘要:传送门 解题思路 求2-sat合法的方案数。 做法: 先基操判断有无解,并求出一组解。 然后考虑两个集合的人能否过去。 我们发现只有三种情况:A到B一个人,B到A一个人,AB交换一个人。 所以就 判断AB集合中的人是否符合条件,最后方案数即为(A到B符合的人数+1)*(B到A符
阅读全文
摘要:传送门 解题思路 和板子几乎一样。 而且不用输出方案。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<q
阅读全文
摘要:传送门 解题思路 思想:将问题转化为图论问题。 因为一个点只有两个状态,所以每个点可以拆成 i 和 i+n 两个点,u 连向 v 表示选择 u 就必须选择 v。 根据条件建图(注意一定要建对应的反向边(例如建立 u->v+n,就必须再连 v->u+n))后,跑一遍Tarjan求强连通分量。若发现存在
阅读全文
摘要:传送门 解题思路 考虑尺取法。 将所有区间按照长度从小到大排序,然后tow-pointers在保证区间最大值>=m的情况下不断维护区间+1/-1。 用线段树维护。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<
阅读全文
摘要:总结 场上做了ABCD1E,但其实题目都挺简单的,还是自己太菜了,唉。 %%%xmz神仙,AK了。 A. Elections 求使一个数变成三个数中最大的数最小加几。 做法很多,但是注意不能直接求max然后减,要判断。 B. Make it Divisible by 25 因为25是100的因数,所
阅读全文
摘要:传送门 解题思路 和洛谷 P3674 很像。首先对于质数输出其本身。然后对于合数,根据哥德巴赫猜想,偶数一定可以由两个质数相加得到,而奇数则可以由两个或者三个质数得到。 但是三个数的和不好找,于是可以把奇数-1得到偶数进行求解。 然后就可以预处理1~1e7的质数,扔到bitset里,每次询问相当于询
阅读全文
摘要:传送门 解题思路 m:菜数 n:原料数 当 m=n-1 时:最小的跟最大的两两结合。 当 m>=n 时:最大的单独做,最后就变成了 m=n-1 的情况。 当 m=n-2 时:将每个物品减去k后做01可行性背包,可以使用 bitset 优化。 具体证明可以看这里:题解 P6775 【[NOI2020]
阅读全文
摘要:推荐博客:扶苏的bitset浅谈 笔记: 定义时可以赋值 bitset<10> b(8);bitset<1005> b(string("01010101")) 会分别存储为0000001000、0001010101 函数 b.to_ulong() 和 b.to_ullong() 会把b里面的数转化为
阅读全文
摘要:传送门 解题思路 今晚csp报名网站炸了QAQ,发布新闻者禁三警告 先考虑暴力dp: O(na)的想必大家都会,但一遍都做不下来。 所以需要换一种dp。 假设求序列[l……r]的答案。 先将其排序,假设到第i-1位时能表示出来的范围为[1..x],则只要判断第i位是否大于x+1即可。 若小于x+1,
阅读全文
摘要:传送门 解题思路 线段树维护区间最长连续0的长度。 板子。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include
阅读全文
摘要:传送门 解题思路 被细节卡了一上午wwww 很好地一道题,考察了AC自动机的本质。 先考虑如何暴力做:枚举y中的每一位,并不断跳fail,若跳到了x,则ans++。 如何优化这个过程呢? 先离线根据y从小到大排序。 当我们以0为根节点,fail[now]向now连边时,AC自动机就变成了一颗树。这时
阅读全文
摘要:传送门 解题思路 对于这种求次短路的题,很常见的套路是先求出以起点和终点作为源点到其他各点的单源最短路,然后枚举每一条边,可以发现次短路一定是重复经过某一条边或者走了这条不在最短路中的边。分类讨论即可。 注意本题中有重边和自环,且计算度时,重边算一次,自环也算。 AC代码 #include<iost
阅读全文
摘要:传送门 解题思路 设dp[i]为先i位能否被理解。 然后在AC自动机上匹配,若 num[j]&&dp[i-cnt[j]] 则 dp[i] 等于 1。(j为不断fail的指针) AC代码 #include<iostream> #include<cstdio> #include<cstring> #in
阅读全文
摘要:传送门 解题思路 先对所有的string跑一遍AC自动机。 用sum表示到达一个节点的收益,可以在求fail时顺便继承着fail节点的sum值。 然后在这个AC自动机上做dp即可。 设dp[i][j]为第i步走到AC自动机上的j号节点的最大分数,枚举转移到的点数转移即可。 AC代码 #include
阅读全文
摘要:传送门 解题思路 来pyyz过掉的第一题祭 一开始在前来个模板上改了改,发现T飞了。 看一下题解发现,因为标记不会清空,所以会被卡到O(ST)。 于是考虑优化。 因为AC自动机本质上是一个有向无环图,所以考虑每次更新答案时只更新到当前节点,最后拓扑排序遍历一遍图统计答案即可。 复杂度降到了O(S+T
阅读全文
摘要:传送门(简单版) 传送门(加强版) AC自动机 推荐阅读:洛谷日报 讲的真的很好。 我没法再说的更好了。 甚至我的板子都是照着他的敲的。 加强版 说是加强版,实际上只需更改一下num数组表示的含义:从当前点有几个模式串结尾,改成以当前点结尾的模式串的编号。 在查询过程中也不需要清空num标记。 注意
阅读全文
摘要:传送门 解题思路 看出是区间dp,但是就是不会设计状态,不会写状态转移方程/kk/kk 设dp[i][j][k]表示区间i到j加上左面连续k个a[i]的答案。 最后答案即为dp[1][n][0]。 状态转移分为两种情况: 让前k个和第i位连起来处理:dp[i+1][j][0]+w[k+1] 枚举断点
阅读全文
摘要:传送门 解题思路 观察到n非常小,所以考虑状压dp。 问题在于如何确定一个没有后效性的状态/状态转移方程。 设dp[i][j]表示当前已经选择了的行的集合为i(一个二进制数),上一个选择的行是第j行的不考虑首行和末行的答案。 首先转移可以通过提前预处理两行之间的代价优化到O(1)。而首行的选择实际上
阅读全文
摘要:传送门 解题思路 先将u和v二进制拆分,然后从低位向高位考虑。 然后就是大力分类讨论: 当某一位u是1且v是1时,要求这一位有奇数个1且前面有偶数个进位 当某一位u是1且v是0时,要求这一位有奇数个1且前面有奇数个进位 当某一位u是0且v是1时,要求这一位有偶数个1且前面有奇数个进位 当某一位u是0
阅读全文
摘要:传送门 解题思路 先不考虑砝码质量相等的情况,设dp[i][j][k]表示前i个砝码选j个组成重量为k的方案数。 最后判断是否合法就从判断方案数是否为1,变成了是否等于C(cnt,i)。(cnt为某个数字的数量,i表示选取的数量)。 可以滚动掉一维数组。 最后一定要记得特判数字类型只有一种或两种的情
阅读全文
摘要:简单版传送门 困难版传送门 解题思路 单调队列优化dp板子题。 但是要注意一开始把dp数组初始化成极小值。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #
阅读全文
摘要:传送门 解题思路 一开始想到的是类似0/1分数规划的方法进行二分。 后来发现答案可以贪心解决。 我们可以发现最后的答案一定是由若干权值和相同的集合组成的,因为若其中一个集合的点权和较大,则将其单独拿出来显然更优。 所以可以先dfs一遍用树形dp求出最大的集合的大小ans,再dfs一遍,若扫到某个集合
阅读全文
摘要:传送门 解题思路 观察到一个点的点权最多有8个质因数,所以可以存下来进行dp。 设dp[u][i]表示以u为根的子树中的点到u的gcd为u的第i个质因数的倍数的最大距离。 是不是有点绕。多读几遍。我再加个括号。 设dp[u][i]表示 (以u为根的子树中的点) (到u的gcd为u的第i个质因数的倍数
阅读全文
摘要:传送门 解题思路 树形dp。 用dp[i]表示i的子树中的节点到i节点的最大收益。 Q:如何保证路径上任意时刻的收益非负? A:其实不需要管。因为若某一时刻收益为负,则不会去走,而是从零开始。 AC代码 #include<iostream> #include<cstdio> #include<cst
阅读全文
摘要:传送门 解题思路 哈夫曼树(Huffman Tree),就是一棵树满足叶子节点的权值*到根节点的距离的和最小的树。 一开始假设整个图没有任何连边。 然后贪心思想,每次新建一个节点,取k个权值最小的节点作为这个节点的儿子(相当于把节点合并)。 这样每次少k-1个节点,会导致最后一次合并不满k个节点。
阅读全文
摘要:传送门 解题思路 一直往扫描线方面想,结果自己没想出来,还是运用的不够灵活。 其实很简单,对于查询区间[l,r],答案为左端点小于等于r的区间数-右端点小于l的区间数。 维护两个树状数组即可。 AC代码 #include<cstdio> #include<iostream> #include<cst
阅读全文
摘要:传送门 解题思路 注意所有的砝码都是倍数关系,所以砝码质量的种类数只有log级别。 先用类似进制的方式求出质量尽可能多的装砝码方案。 然后再在其基础上进行贪心调整——砝码质量小的尽可能多用。 所以从小到大进行贪心选择即可(仿照减法借位) AC代码 #include<iostream> #includ
阅读全文
摘要:传送门 解题思路 可以自己取一个大质数当做模数,或者直接利用unsigned long long的溢出。 进制也可以选择一个较小的质数,如13131或者15151等。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #includ
阅读全文
摘要:传送门 解题思路 首先很显然可以贪心进行选择,枚举哪个数字有k个,然后优先绝对值更靠近他的数字,即可算出最小代价。 下一个要求是字典序最小。 还是先删掉绝对值靠近他的点,先从前往后正序删比他的的数字,再从后往前逆序删比他小的数字,即可保证字典序最小。 AC代码 #include<iostream>
阅读全文
摘要:传送门 解题思路 概括一下题意:求字符串中abababa子序列的个数。 考虑dp。 设dp[i]表示以子序列第i位结尾的方案数。 显然第i位是'a'时dp[i]才不为0。 转移方程为: 其中k为上一个b出现的位置。 显然可以边求dp边记录
阅读全文
摘要:传送门 解题思路 按照字符在a中出现的位置映射到b字符串中。 求逆序对数即为答案。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<iomanip> #include<vector
阅读全文
摘要:传送门 解题思路 先预处理出以1为根节点的各节点的size。 定义一个节点的size为以这个节点为根的子树的a的和。 然后求出ans[1],再进行换根dp求出每个节点的ans,比较大小输出即可。 AC代码 #include<iostream> #include<cstdio> #include<cs
阅读全文
摘要:传送门 解题思路 好板子啊。 要不是是个省选题 我才不写博客呢。 树剖完了,就是单点修改+区间修改+区间求和。 线段树维护即可。 AC代码 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<a
阅读全文
摘要:传送门 Lucas定理 OI-Wiki讲的太好了:http://oi-wiki.com/math/number-theory/lucas/#lucas 做一下总结补充解释: \(f^p(x)\equiv f(x^p) \pmod p
阅读全文
摘要:传送门 解题思路 田忌赛马这道题的加强版。 收回我不能用贪心来解决的话。 排序后每个序列都用两个指针记录已经使用的数的位置。(一定先使用两边) 具体策略为: 若最大的比对方大,则最大的上。 若最小的比对方大,则最小的上。 否则就用最小的打对面最大的。 AC代码 #include<iostream>
阅读全文