刷一下集训队作业了(然后我CSP就退役了)
如果不是自己想出来的会写一个“不会”(然后整篇文章里全是不会)
AGC023E
不会
先考虑合法的排列个数,记(cnt_j=sum_{i=1}^n [a_igeq j]),则(ret=prod cnt_j-(n-j)),也就是说从大到小依次放(n)到(1),每个数可以放的位置就是(cnt_j-(n-j))
考虑对于一对(i<j),如果(a_i=a_j),那么这满足(p_i>p_j)的排列数恰好为({retover 2})
如果(a_i<a_j),那么如果(p_jin [a_i+1,a_j])的时候都不会有逆序对产生,只有(p_jleq a_j)的时候有,所以我们可以令(a_j=a_i),然后计算此时的排列个数,乘上({1over 2})就是此时这一对的答案了,不过注意如果我们修改(a_j)会对(cnt)造成影响,具体是使([a_i+1,a_j])区间内的(cnt-1),那么令(D_i={cnt_i-1-(n-i)over cnt_i-(n-i)}),那么方案数就变成(ret imes sum_{k=a_{i}+1}^{a_j}D_k),可以写成前缀的形式,即({sum_{k=1}^{a_j}D_kover sum_{k=1}^{a_i}D_k }),那么用树状数组维护前面所有合法的({1over sum D})的和即可。记得有的(D)可能为(0),那么对于每个(i)只统计它前面不为(0)的那一段的答案即可
如果(a_i>a_j),不太好算,正难则反,考虑计算(p_i<p_j)的方案数,这个就和上面的差不多了,再用总的排列个数减去这个就行了
AGC032F
不会,概率期望神仙题
首先是一个神仙的转化,我们令其中一条边为起点,然后顺时针每({2over 3}pi)划分为一个区域,三个区域中的线段分别染成红绿蓝三种颜色,然后把所有线段(mod {{2over 3}pi})之后搞到同一个区间里,那么问题可以转化为在([0,{2over 3}pi])里,随机取(n-1)个点把它划分成(n)条线段,每个点颜色随机,求两端颜色不同的线段长度最小值的期望。注意(0)处视为红色,({2over 3}pi)处视为蓝色
我们先来考虑一个一般的问题,一个长度为(1)的线段随机分成(n)份,第(k)短的长度的期望(记为(E(L_k))),这个见这里的(6)
然后最终的答案就是
也就是说,(E(L_i)-E(L_{i-1}))会被算入贡献,那么前(i-1)短的线段都得两端同色,概率是({1over 3^{i-1}})。那么直接代入计算即可
upd:其实这里不用差分也可以,那么答案就是
特别注意当(i=n)的时候概率和之前不一样,因为所有(n-1)个点的颜色都选好了所以它没得选了,也就是说不用额外乘上一个({2over 3})了
CF516D
由于到某个点距离最远的点必定是直径的两个端点之一,所以如果我们记两个端点分别为(s,t),记(D_u=max(dis(u,s),dis(u,t))),那么如果我们取直径的中点作为根(即(D_u)最小的(u)),那么这棵有根树必定满足(D_ugeq D_{fa_u})。然后把所有点按(D)排序,枚举连通块中深度最浅的点(同时也一定是(D)最小的点),然后用双指针维护一下就行了,连通块大小用并查集的(size)维护即可
ARC098F
去除掉捐给每个点(b_i)的花费之后,我们二分还需要的钱数(mid)
(check)的时候正难则反,如果我们已经确定了最终点(rt(a_{rt}-b_{rt}leq mid)),我们需要知道能否从这个点扩展到其它所有点。当扩展到一个新的点时,我们可以选择取出这里的(b),也可以选择不取(但是这里显然是取了更优)。所以如果记当前已经经过的所有点的(sum b=sum),那么对于一个新的点(u),它能被扩展到,当且仅当它与某个已经被扩展的点相连,且(a_u-b_u-midleq sum),二分之后左边就是个定值了,所以我们可以用堆维护所有可以扩展的点,每次取出最小的来扩展,这个贪心显然是最优的。同时,如果合法,对于原问题,按每个点被扩展的顺序倒序捐款即可
然而我们不能确定最终点,也不可能枚举。不过我们发现这个最终点可以用类似多源最短路的方法优化,即,从每个合法的点开始扩展,如果两个连通块在某时刻相连了,记(mx)表示连通块中最大的(a_i-b_i-mid),对于(mx)较大的那个连通块,走完这个连通块的时候另一个肯定全都是可以被拓展的了,那么直接合并就行了。那么两个连通块合并的时候用启发式合并来维护他们可以拓展的点的即可就行了,总复杂度(O(nlog^3 n)),不过似乎跑的海星
upd:据说可以直接树形dp,首先贪心的想,肯定是最后一次经过某个点时把钱捐掉,令(c_i=max(a_i-b_i,0))那么等价于任何时候在(c_i)时至少要有(c_i),再贪个心,对于(c_i)最大的(i),我们捐完之后进入了删掉(i)之后的一个连通分量(G),然后肯定不会再回来了。而且如果(G)中有一次捐钱是在(i)捐钱之前的那么肯定可以扔到(i)捐钱之后。所以顺序一定是捐完(i)的其它连通分量,捐(i),捐(G)
我们以(i)为根然后把(i)删掉,递归所有连通块,以这一层的根连向上一层的根,这就是一棵树了,令(f_i)表示遍历完(i)的子树所需的最小钱数,(s_i)表示捐完(i)的子树所需的最小钱数(即子树内的(sum b)),初值为(f_i=s_i+c_i),然后枚举捐完(i)之后去了那棵子树,转移即为(f_i=min(f_i,s_i-s_v+max(f_v,c_i))),算上建树时的(sort),总复杂度(O(nlog n))
CF679E
不会
其实很套路,由于(42)的幂次在(longlong)范围内只有(11)个,那么你对于每个数(x),设最小的大于它的(42)次幂为(p),那么记录一下(d=p-x),每一次区间加之后,如果区间中最小的(dleq 0),那么就暴力把它更新,这样的话,如果只有区间加,总复杂度就是(O(11nlog n)),然后区间覆盖的话,那么在之前那里如果一段区间值域相同,同时更新就好了,根据势能分析那套理论,复杂度还是(O(11nlog n))
CF506C
不会,可以退役了
首先二分答案(mid),那么每个竹子被砍的次数就是(leftlceil{h_i+m*a_i-midover p} ight ceil),而且可以证明次数不会更多。我们可以求出(d_{i,j})表示如果在竹子(i)上砍(j)刀,那么第(j)刀最早要在第几天砍。具体实现就是对于每个(j=(h_i+m*a_i-mid-1)\%p+1+kp),求出砍掉这么多至少要在第几天就是了,最后累加,不符合条件就gg
AGC023D
怎么又不会
首先我们发现,如果(p_1geq p_n),那么哪怕(n)把车拉到了(n-1),接下来也一定是先把(1)送回家再送(n),即有(T_n=T_1+x_n-x_1),那么(n)需要令(T_1)最小,所以他肯定会跟(1)的票,那么可以让(p_1+=p_n),然后删掉(n),如果(p_1<p_n)同理,一直这样下去直到所有点都在(S)同一边即可
AGC032E
如果写出暴力,就是(sort)之后枚举一个分界点,两边都是最大和最小值配对,那么二分最终的答案,对于每个(a_i),会导致它和两段区间不能匹配(其中一段是加起来小于等于(m)且大于(mid),另一段是大于(m)且大于(mid+m))对于其中任意一段区间,把对应的分界点找出来,不可行的分界点也一定是一段区间,那么区间覆盖,如果最后找到某个没有被覆盖的分界点,那么就可行了
upd:看完题解人傻了,这题似乎最优的分界点一定是满足右边每一对都是大于等于(m),且是所有合法的分界点中最右的,直接二分出这个分界点就行了
CF555E
首先同一个边双内肯定存在某种定向方案使得它成为一个强联通分量,那么我们把边双缩点之后成了一棵树,每一次相当于把(u)到(LCA)的边变成向上,(LCA)到(v)的边变成向下,看成染色,用树剖+珂朵莉树解决就行了
upd:据说染色这部分可以用树上差分离线解决
AGC022E
不会
原题解两个做法都看不懂,然后看到一个神仙,手动建了一个“毕克自动机”
一个串是好的当且仅当它最终在(1)或(2),手玩一下大概可以证明上述这个自动机的正确性。那么我们在自动机上(dp)就行了
AGC029F
不会
神仙结论题,首先树有一个性质,对于任意一个节点(u),如果以它为根,那么剩下的每个点和它父亲那条边可以刚好构成一个完美匹配,所以,一个必要条件就是,对于任意一个(u),以它为根,然后建一个二分图,左边是剩下的(n-1)个点,右边是那(n-1)个集合,左(i)右(j)有边当且仅当(i)在(E_j)中,那么任意一个这样的集合都要有完美匹配
事实上,这个条件也是充分的,假设分别以(u)和(v)为根,并把两个完美匹配给取并,那么一定会存在一条从(u)到(v)的路径(因为只有(u,v)的度数为(1),其余度数都是(2))。这个代表什么呢?它表示,我们先随意取一个根跑个完美匹配,然后建一张新图,如果对于某个(i),有(x,yin E_i)且(E_i)的匹配对象是(x),那么就连边((x,y)),然后我们从根出发开始跑,如果对于其它所有的根也满足条件,那么(u)肯定能遍历到所有其他节点(相当于沿着路径修改匹配)
那么对于这个新图,任意取一个(dfs)生成树就是答案了
CF576D
定义一个矩阵,其中(T_i)表示在第(i)秒时是否能在某个点,以及(G_i)表示小于等于(i)秒前是否到过某个点,如果不考虑加边的情况,那么(T)的转移矩阵就是邻接矩阵,(G)的转移矩阵就是邻接矩阵中令每个(a_{i,i}=1)
然后要考虑加边,对于(T)还是可以直接算,只需要改一下邻接矩阵即可,但是对于(G),我们需要重新计算,因为只有一整段时间内都没有加边的情况下才能用上面说的那个矩阵来转移。所以我们先计算出(T_{t_i}),然后这一整段内都可以用(T_{t_i})乘上转移矩阵来转移了
然后我们二分答案,对于当前答案(mid),直接二分找到对应的(t),预处理一下前缀(t_i)的答案和对应的转移一下就可以了
这样的话复杂度大概(O(n^4log n)),不过我们发现这个矩阵中所有元素都是(0/1),bitset优化一下就行
AGC039D
做过,这里
CF639F
发现合法的条件就是所有点在同一个边双里,那么先把原图按边双缩成一棵树,询问的时候把虚树取出来,边连起来,tarjan一遍整棵虚树来缩点就行了
看错了强制在线的方式居然还能炸胡过样例
CF506E
不会,妈耶现在字符串上数数题都流行自己建一个自动机的么
首先记(m=|S|),可以想到一个(O(nm^2))的dp,一个回文串合法当且仅当(s)是它的一个子序列,所以记(f_{i,j,k})表示考虑了回文串的前(i)个字母(同时也确定了后(i)个),成功匹配完了(s[1,j-1])和(s[k+1,m]),根据(s_j)和(s_k)是否相等有两种转移
以(s=abaac)为例,图大概长这个样子(其中红点和绿点表示两种不同的转移)
节点数(O(m^2)),矩乘也优化不了了
接下来方便起见我们先考虑(n+m)为偶数的情况,我们发现每一次转移,一定是经过一条链最终到达终点,且链上每个点连了自己很多自环,对于一条链,上面如果有(k)个红点,那么绿点的个数就是(lceil {m-iover 2} ceil),而且对于同一条链,上面红点绿点顺序对答案没有影响,所以可以直接dp出(g_i)表示经过了(i)个红点的链的条数,然后可以建出一张新的图,即把所有绿点连成一串,所有红点连成一串,第(i)个红点向第(lceil {m-iover 2} ceil)个绿点连边
这样点数就可以优化到(O(|S|)),可以矩乘了
如果是(n+m),我们先进行({n+m+1over 2})次矩乘,然而发现如果存在某个(s_i=s_{i+1})且这两个都是被(S)最中间那个字符匹配的话,实际上是不合法的,但是被我们算进去了,所以要去掉这种情况,我们建一张新图,红点绿点之间的边为走过(i)个红点之后待匹配的为(k)和(k+1)且(s_k=s_{k+1})的方案数,且去掉最终终点的自环,这样方案数就没问题了
然后还需要一点常数优化,因为我们发现这是个(DAG)且只会从标号小的转移到标号大的,那么矩乘的时候枚举(i,j,k)只要保证(ileq k)且(kleq j),这样就可以过了
AGC022F
不会
我们考虑,如果某一次是(B)向(A)跳的,就从(B)向(A)连边,这样的话某个点的系数就是(2^{深度})乘上一个(pm 1),由于基数很大,我们可以认为只要两个方案中某个点的系数不同则这两个方案不同
对于某个点,如果它多了一个儿子,那么其它儿子中的所有点的(pm 1)都会取反。所以如果一个点有(k)个儿子,那么其中有(lfloor{kover 2} floor)个儿子会被取反,而且如果(k)为奇数,自己也会被取反。所以如果我们已经知道了这棵树,那么每个点上的正负状态就是父亲的正负状态异或上父亲的儿子个数的奇偶性异或上自己的儿子个数的奇偶性
发现如果正负状态和父亲的正负有关很麻烦,我们考虑差分。建立一棵新树,其中某个点为(1)当且仅当它在原树中和父亲的正负相同(否则为(-1)),这样新的一层中点的状态只和上一层中奇数儿子的点的个数有关,然后考虑从上到下dp
设(f_{i,j})表示考虑了(i)个点,其中最后一层有(j)个节点有奇数儿子的方案数,然后转移的时候,我们枚举新的一层中有(x)个点为(1)(即在原树中和父亲相同),(y)个点为(-1)(即在原树中和父亲不同)。如果先不考虑自己作为奇数点的影响,那么这一层实际为(1)的点数是(j+{x+y-jover 2}),相当于每个奇数点先自带一个,然后剩下的成对出现
所以我们要把为(1)的点数调整到(x),就需要取反(|j+{x+y-jover 2}-x|)个点,而这几个点会被取反就说明它们是这一层中的奇数点,转移过去就行了
总复杂度(O(n^4)),优化一下可以到(O(n^3)),懒得写了
AGC028E
不会
首先肯定需要按位贪心,那么我们假设现在已经确定了某个前缀,判断对于后面的所有元素是否存在某种方案使其合法
假设把剩下的数字分成了(C,D)两个集合,其中(C)接在(X)后面,(D)接在(Y)后面,那么有一个结论,就是(C)或(D)中必定有一个满足这个数列中的前缀最大值的全都是(P)中的前缀最大值
对于必要性,可知(P)中的前缀最大值在分完之后一定仍然是前缀最大值
对于充分性,如果(C,D)中都存在前缀最大值且它们不是(P)中的前缀最大值,那么我们交换它们,对于这种值来说,导致它不是(P)中前缀最大值的位置一定恰好在另一个集合中,这样我们使两个集合的前缀最大值个数同时减一,且仍然满足条件
我们先假设(C)满足这个条件((D)满足的情况同理)
记现在(X)中的前缀最大值个数是(cx),(Y)中的前缀最大值个数为(cy),(X)中当前最大值为(mx),(Y)中当前最大值为(my),并且已经确定了([1,i])的前缀,([i+1,n])中作为(P)原本的前缀最大值个数是(Q),而(D)中有(k)个前缀最大值是(P)中原来的前缀最大值,有(k)个新增的前缀最大值,则需要满足条件
前面是个定值,而对于后面,我们可以把(P)中原来的前缀最大值记为(2),其他值记为(1),问是否能从([i+1,n])中选出某个序列使得所有前缀最大值贡献之和等于前面那个定值。我们发现如果我们可以取到(x),那么也一定可以取到(x-2),所以我们分别维护(x)为奇数和偶数时的最大值
(D)满足条件的情况也同理
然后用(f_{i,0/1})表示以(i)开头的,贡献总和为奇数/偶数的最大值,用线段树优化转移即可
CF512D
这个世上最尴尬的事情应该就是成功想出来了真算法却伪证成是假的了……
首先对于不同连通块就是个指数型生成函数的事,而同一个连通块我们先按边双缩点,那么最终一定是一棵树
先考虑这个连通块中存在某个大小大于一的边双的情况,那么缩完点之后所有这样的点都不能被选,而且任意两个这样的点路径上的点也不能被选,那么我们随便找一个这样的点做根,一个点可以被选的充要条件就是它的子树中不存在这样的点,而且这种可选连通块中深度最小的点一定是最后被选的,那么我们直接以那个深度最小的点做一个树形(dp)就行了。具体dp的过程就是把儿子的(EGF)乘起来,记这棵子树大小为(size),那么选择(size)个点的方案数等于(size-1)个点的方案数(记得是(EGF)所以这里实际上还要除以一个(size))
然后考虑这个连通块就是一棵树的情况,这样的话每个点都有可能最后被删,我们枚举最后被删的点作为根做一遍树形dp,最后把所有的(EGF)加起来,那么一个删去(i)个点的方案会在其它(n-i)个节点作为根时被统计到,除以(n-i)就行了
最后把所有的(EGF)乘起来就行了,对于一棵树做一遍树形dp的复杂度是(O(n^2)),总复杂度(O(n^3))
AGC020F
做过 这里
AGC037E
做过这里
CF559E
不会
这题好像各种神仙dp解法……
先把所有坐标给离散化,记(pos_j)为离散后为(j)的坐标的原坐标,(p_i,l_i,r_i)分别为灯的坐标,往左照时的端点,往右照时的端点,按(p)排序之后,记(f_{i,j})表示考虑完前(i)盏灯,前(j)个位置被覆盖的最大长度
初始时(f_{i,j}=f_{i-1,j}),如果第(i)盏灯往左找,则(f_{i,j}=f_{i,l_i}+pos_j-pos_{l_i},jin [l_i,p_i])
如果往右照会比较麻烦,对于某一盏灯(k)满足(p_k>p_i)且(l_k<l_i),如果(p_k>r_i),那么(k)往左找就会把(i)给直接覆盖,不用管,然而(p_k<r_k)且(k)往左照的话,有可能会把(i)左边的一段给照到,但是我们更新不了答案
所以一种方法是先对每一个(j)记一个(bl_j),表示满足(p_i=j)且(l_i)最小的(i),记一个(las),初始为(f_{i-1,p_i}),然后枚举(j)从(p_i+1)到(r_i),每次用(las+pos_j-pos_{p_i})更新(f_{i,j}),并且如果(l_{bl_j}<p_i)的话,我们还要用(f_{i-1,l_{bl_j}}+pos_{p_i}-pos_{l_{bl_j}})来更新(las)
注意这里必须先更新(f)再更新(las),也就是说(f_{i-1,l_{bl_j}}+pos_{p_i}-pos_{l_{bl_j}})只能用来更新(j+1)及以后的答案,否则会导致(bl_j)的最优策略里会既往左照又往右照
时间复杂度(O(n^2))
AGC039F
做过 这里
CF639E
精度问题感人……
首先如果我们确定了一个(c),提出所有常数项之后发现就是要使得(sum p_ix_i)最小,也就是说一个(t_i)会产生(t_i imes sumlimits_{k=i+1}^n p_i)的贡献,然后我们发现如果(i)和(i+1)满足(t_i imes p_{i+1}<t_{i+1} imes p_i),那么交换(i)和(i+1)之后答案更优,所以直接按({t_iover p_i})升序排序就行了
然后要对于任意最优序列都合法,那么某段连续的({t_iover p_i})相同的可以随便排列,对于每个算出它最大和最小的(x_i)就行了。对于某个(p_i>p_j)合法的条件是(p_ileft(1-c imes {x_iover T} ight)geq p_jleft(1-c imes {x_jover T} ight)),化简一下就是(cleq {p_i-p_jover p_ix_i-p_jx_j}T),(事实上会有(p_ix_i-p_jx_jleq 0)的情况,不过这种情况下(c)需要大于等于某个负数,显然合法的),那么直接把所有的按照(p)排个序,对于每个(p_i)和(p_{i+1})算一下就行了。顺便记得最后算的时候(p_ix_i)会炸精度,上下同除以一个(p_ip_j)就行了
CF575A
一眼题,直接线段树维护矩乘,然后分段就行了,细节非常多,调的要死了
AGC031F
由于某些原因这题咕了
AGC033D
不会
我们发现答案的数量级是(O(log n))级别的,那么我们可以考虑一轮一轮做,设(f_{i,j,k})表示左上角为((i,j)),右上角为((i,k)),(T)轮之后往下最多能扩展几行,同理定义(g_{i,j,k})表示左上角为((j,i)),左下角为((k,i)),(T)轮之后往右最多能扩展几行,每一轮都用这两个互相转移就行了
CF547D
我们把所有的点看做是二分图的边,然后每个横坐标或者纵坐标当成二分图的点,问题就转化成对于每个点它选出的边数得是它的度数除以二(如果是奇数也可以是除二上取整),新建(S,T)然后对两边的点连边,转化成一个上下界可行流就行了。
这题数据是真的水,可行流没有连从(T)到(S)的那条边竟然能炸胡那么多点……
upd:据说可以转欧拉回路(O(n)),或者直接(O(n))染色
ARC097F
有一只猫锟和一棵树可太真实了……感觉网上别的树形dp都好麻烦的样子
先把所有黑色的叶子剥掉,一直到所有的叶子都是白色为止
先考虑一种最简单的遍历,就是从某个节点出发按(dfs)序遍历每个节点,这样每条边会被经过恰好(2)次,每个点会被经过(deg_i)次,然后在每个点上再单独考虑一下这样之后是否变成了黑色,不是的话还需要一次额外的次数。我们记这种情况下的总次数为(sum)
能减少次数的唯一办法,假设起点和终点分别为(S,T),那么从(S)到(T)的最少游走次数就是在上面的基础上,(S)到(T)路径上的每条边都少走一次,路径上的每个点(不包括(S)和(T))也都少走一次。那么我们可以去掉(S)和(T),考虑中间那条链最长能选多长就行了。中间那条路径删掉之后的贡献就是点数(+1-)黑点个数(+)白点个数(这里的颜色为朴素游走之后的颜色),那么可以当做黑点贡献(0),白点贡献(2),求一条两端点不在叶子上的最长链的长度(res),这东西随便dp,最后的答案就是(sum-res-1+1)
CF671D
很容易想到(O(n^2))的dp,设(f_{i,j})表示覆盖完(i)的子树,且可以往上覆盖到一个深度(leq j)的祖先的最小代价,转移的话显然,就是保证每个子树里选的状态的(jleq dep_i)即可,然后我们发现每个(f_i)都是由若干个代价相等的区间连起来的,我们可以把它们一起考虑,用(map)缩个点就行了,同时启发式合并维护(map),这样的话每个点最多被插入(O(log n))次,最多删除一次,复杂度(O(nlog^2 n))
upd:据说可以强行把它看做一个线性规划问题然后转对偶,就变成了每条边可以选若干次,每条链上所有边被选的次数之后小于等于给定值,最大化边被选的总次数,可并堆维护一下就行,复杂度(O(nlog n))
CF547E
先考虑(call(i,j))怎么计算,如果对(i)乱搞然后用(j)去查询,那么推广到原题上就根本不可做。所以正难则反,我们考虑先对(s_j)建一个(SAM),然后用(s_i)去这上面查询,每一次匹配的长度等于(s_j)的长度,那么答案(+1)。那么就可以理解为(s_i)在一个(SAM)上匹配,每匹配一个字符之后到达了新节点,会把当前节点到根的所有节点的贡献(+1),而对于一个(s_j),它在(s_i)中出现的次数就是(s_j)代表的节点的权值
那么就可以了,我们先对所有串建一个广义(SAM),然后把询问拆成((l-1,k))和((r,k))的形式,每一次加入(s_i),让它在这个广义(SAM)上匹配,并把经过的节点的贡献加上去就行了,树剖+树状数组就行了
upd:据说更套路的方法是直接线段树合并维护一下就行了