代码自己去uoj上看,懒得放链接了(
2015
k小割
强 行 三 合 一
前10分爆搜割集,然后check即可
后面40分,大概所有不是源点汇点的点都和源点有边,和汇点有边,那么每个点连的两条边要选一条/两条割.设其中较小权值为\(a\),较大权值为\(b\),那么一个点有三种状态\(\{a,b,a+b\}\),初始都为第一种,那我们保存状态集合,然后每次选最小的状态输出,然后拓展出次小的状态,这个拓展要么是当前指定点的\(a\)变成\(b\),或者\(b\)边\(a+b\),要么是后面找一个点的\(a\)变成\(b\)(满足\(b-a\)比当前点\(b-a\)大),后面一种拓展可以改为当前点由\(b\)变\(a\),下一个是后面一坨点中\(b-a\)更大的且最小的点,他从\(a\)变\(b\)
最后50分,考虑记录一些割状态,每次选最小的,然后拓展出次小割状态,次小割一定要么是强制选择一个没被割的边,要么强制不割某条割边,换一条边割,具体拓展方法是维护这个状态的强制选与不选的边集,然后先处理这些边(强制选的强制断开并加到答案里去,强制不选的把容量改为\(\infty\)),再跑个最小割,然后找出次小割,而次小割一定是某条不在割集中的边割掉产生的,那这条边就会代替割集中的一条边,枚举这条被代替的边\((x,y)\),那么新的边一定在残量网络中\(S\)到\(x\)的最小割上,或\(y\)到\(T\)的最小割上.考虑这么做的正确性,一个割集的次小割一定由割集与最小的边有关,这条边要么在割集中,要么不在,那么用上面的方法就可以考虑到这两种情况
混淆与破解
留坑待填
未来程序
task1
\(ab\mod c\)
task2
打表可得为\({fib_{n-1}}^2\)
task3
要求\(n,\sum i,\sum i^2,\sum i^3,\sum i^4\),利用\((i+1)^k=\sum_{j=0}^k\binom{k}{j}i^j\)设计矩阵,矩乘后即可全部求出来
task4
如果方格里有\(a\)个位置为\(1\),那么count1
答案为\(a^2-a\)
count2
是求对于每个为\(1\)位置,离它最近的为\(0\)位置的曼哈顿距离,直接把为\(0\)位置丢进队列开始bfs,对每个位置求最近曼哈顿距离即可
task5
求全\(1\)子矩阵个数,可以先固定上下界,然后如果某一列在这个上下界中全为\(1\)就把对应位置标\(1\),然后就是求全\(1\)连续段问题.因为一个极长的\(1\)(长度为\(l\))的贡献为\(\frac{l(l+1)}{2}\),那么可以考虑改为先枚举下界,上界依次往下移动,然后对于新增的全\(1\)列就减去前后两个连续段贡献,合并之后加上新的贡献,可以利用并查集维护
task6
这题只能找循环节来做,但是暴力用map找不行,floyd也不大行,考虑brent算法,维护两个指针以及一个\(lm\)值,每次移动第一个指针,如果找的过程中第一个指针和第二个相遇了就说明找到了环,如果第一个指针移动步数\(=lm\)就把第二个指针移到第一个指针处,同时\(lm=lm*2\)
task7
高级版数独,搜的时候维护每一行,每一列,每一个方阵是否放了某个字符,如果这个字符没在当前行/列/方阵出现过才能放;以及每次从能放字符数量最小的开始放
task8
偏序关系计数,大概偏序关系为若干\(DAG\),写出统计柿子然后推一推即可. 每个\(DAG\)都是独立的,可以分开算.然后对于一个\(DAG\)我们考虑枚举这个上面的数有多少种相同的,然后状压dp算出在有\(i\)种相同的数的情况下,上面的数分别为其中某一种数的方案数,然后这个\(DAG\)贡献为\(\sum dp_{|S|,i}\binom{n}{i}\),最后乘法原理合并
task9
前四个不解释,枚举/搜索即可
1984
123456
chenlijie
$_$
后六个中,前四个都是单个单词,第五个为单词+空格+单词,第六个为单词+单词.不知道你们有没有注意到第二个cpp(或第十个cpp)中有个词典,直接在里面选单词搜即可
名言为we hold these truths to be self-evident
task10
可以通过dp技巧算出每个字母对应是加几次___
,然后每个单词可以看成是每一位上的字母要用若干次,可以根据他的含义设计出\(dp_{i,j}\)表示长度为\(i\)的串,第\(j\)位算的次数,转移按照他的意思转移即可(每个真子串都要算一次)
2016
挑战NPC
考虑对一个篮子放的球数所产生的贡献入手.如果是0或1个球就产生1的贡献,如果时候2或3个求就产生0的贡献.不妨把这个贡献考虑到匹配上去,即如果一个篮子只有0或1个球匹配,就利用额外的一个匹配产生贡献.具体做法是可以将一个篮子拆成三个点,然后连成三元环,再把原来的每条边拆成三条边连到对应点上,跑个带花树,求出来的最大匹配-球数就是答案.构造方案直接输出对应球的匹配点即可.注意带花树时要从球点开始做,否则球点可能没有匹配点(虽然答案是不变的)
论战捆竹竿
here
鏖战表达式
一开始看成鏖战多项式
区间翻转+可持久化,显然是可持久化Treap.具体实现时,因为合并要讲究优先级,那么每个合并Treap的时候先比较符号优先级(元素一定是叶子节点),再用随机权值比较即可.剩下的东西基本上都可以在普通平衡树以及文艺平衡树中找到,实在不会去百度啊,实在是懒得讲了QAQ.可能实现时要注意卡操作常数,例如一开始建树要建的尽量平均
2017
\(\large\mathcal{WDNMD}\)
待填...
2018
通道
不妨先考虑两棵树怎么做,我们要求的是\(dis1(x,y)+dis2(x,y)\),这等价于\(de1_x+de1_y-2de1_{lca1(x,y)}+de2_x+dis2(x,y)\),那么我们dfs第一棵树,并考虑\(lca1(x,y)\)的贡献.我们在第二棵树上的每个点下面都加一个点\(x'\),连边边权为\(de1_x\),那么点对\((x,y)\)剩下的贡献就是第二棵树上\((x',y')\)的距离.在第一棵树上我们就在lca处合并两棵子树,然后计算\(x,y\)分别在两棵子树内的贡献,就是路径两端点分别为两棵子树对应在第二棵树上的点的最长路径,也就是直径,我们维护第一棵树子树内所有点在第二棵树上的虚树的直径(只要维护两端点),合并的时候只要让两个子树的对应的四个点两两组合取最长路径就是直径
然后是三棵树.我们对第一棵树使用边分治,因为这样可以把树分成两部分,方便计算贡献.然后这条重心边分开的两个子树,把这里面的点分别称为A点以及B点,并在第二棵树上建虚树,然后在虚树上dfs,每次在某个lca处统计不同子树内A点到B点的贡献.因为在第一棵树上用了边分治,以及第二棵树上枚举lca,那么\(dis1(x,y)-2de2_{lca2(x,y)}\)现在是确定的,还剩下\(de2_x+de2_y-dis3(x,y)\),这里就参照两棵树的做法,维护子树内AB点集的直径,然后类似的做就完事了
州区划分
先考虑暴力做法,设\(f_s\)表示选出的点集为\(s\)的答案,这是因为你新加进来一个省,它的贡献只和自己以及前面加过的点有关,转移直接枚举下一次加进来的子集.这里一个子集能加进来说明不存在欧拉回路,也就是只要这个点集导出子图不连通或者存在度数为奇数的点即可.复杂度\(O(n^22^n+3^n)\)
然后可以发现刚刚的\(O(3^n)\)的算法是在做一个叫子集卷积的东西,这个子集卷积有点像位运算卷积,不妨先往\(FWT\_or\)上考虑.我们想要的是\(f_s=\sum_{t\subset s} f_tg_{s\setminus t}\),可是\(FWT\_or\)计算的是\(f_s=\sum_{t|d=s}f_tg_d\),这会导致两个有交的子集的贡献被算进来.那就考虑什么样的两个子集并起来没有交,可以发现如果我们加一维表示集合内1的个数,那么一个卷积合法就要使得\(popcount(t)+popcount(d)=popcount(s)\),所以当状态为\(f_{s,i}\)时,状态合法当且仅当\(popcount(s)=i\),这个在转移的时候注意一下就好了,复杂度\(O(n^22^n)\)
即时战略
其实可以先考虑链的部分分,我们维护当前已经确定的链的两个端点(初始时为1),然后对于没确定的点\(x\)每次选择一边进行\(explore\),如果能得到一个新的点就继续操作直到把\(x\)拓展出来;否则就对另一边进行这个操作.可以证明复杂度为\(o(nln(n))\)
然后是树的做法,暴力是对于当前点\(x\),从根开始\(explore\),如果是已经知道的点就在这个点\(explore\),直到找到\(x\).如果我们是从另外一个点开始的,那么考虑这个点到根的链,我们可以在这个链上二分,如果拓展到一个不在链上的点就可以跳出这条链,并且递归此操作.由这个,以及题目里的点是依次加进来的,就考虑lct维护一些链,因为lct中每个splay都是树上直上直下的一条链,那么从根对应的splay的根开始,每次在这个点上\(explore\),就相当于在这条链上二分,如果询问得到的下一个点在这个点往上方向就跳到这个点在splay上的左儿子,如果在往下方向就跳到这个点在splay上的右儿子,否则直接跳到下一个点的splay上.根据那套理论,复杂度是\(O(nlogn)\)的