由于太懒了,没什么意思的题就写一句话题解了
10.07
分别对(sum a,sum b)开状态开不下,考虑到(a_ileq b_i),所以任意时刻都有(sum aleq sum b),所以设(dp_{i,j})表示选到了第(i)个数满足(sum aleq jleq sum b)的最小代价,显然有转移(dp_{i,j}=min_{k=j-b_i}^{j-a_i}dp_{i-1,k}+c_i),单调队列优化转移即可
两个数异或起来只有两个(1),考虑枚举这两个(1)分别在哪里,即对于(c=2^i+2^j(i eq j)),求有多少对(a_iigoplus b_j=c),拆一下式子变成了((a_iigoplus 2^i)igoplus (b_jigoplus 2^j)=0,i eq j),于是我们能将每一个(a,b)搞成(log)个数,得到了两个(nlog n)长的数列,求一下这两个数列有多少对相等的数对即可。考虑(i eq j)的限制,发现对于原数列一对相等的数,在每一个数位都会被计算一次,于是还要减掉原数列里相等的数对个数乘上数位个数。
通过玄妙的挂链hash能做到(O(nlog n))。写两个(log)基本都被卡了,比如说不会hash的我。
分析一下不难发现对于所有“添”连边得到的图一定是仙人掌(因为保证三线不共点,所以一条边不会出现在两个简单环里)
众所周知,给仙人掌染色最多只需要三种颜色。当且仅当存在奇环的时候,需要用到的颜色数是(3)。我们发现当且仅当有不少于三种斜率的时候一定会存在奇环(三种斜率一定会构成一个三角形,而三角形是一个三元环),于是判断一下是否存在三种或以上不同斜率即可;
不难发现只需要按(frac{t_i}{p_i})从小到大排序之后顺着选过去;修改用线段树维护一下即可。
用一个树上差分能够维护出每一条边被经过的次数,如果选定了根我们贪心的选择经过次数最大的那条边作为重儿子即可。所以随便先定一个根,大力换根即可。由于换根的时候可能会把原来的重儿子换成根,所以对于每个点要维护最大儿子和次大儿子。
(x,y)满足(x)异或(y)在二进制下有奇数个(1)当且仅当(cnt(x)igoplus cnt(y)=1),(cnt(x))表示(x)二进制下(1)的个数。这个结论非常简单,因为(cnt(xigoplus y)=cnt(x)+cnt(y)-2 imes cnt(x&y)),又因为运算在模(2)意义下所以后面那个(2 imes cnt(x&y))相当于没有。于是维护当前区间并内有奇数、偶数个(1)的数分别有多少个即可。
我们把所有区间视为左闭右开的形式,把所有区间的端点拿下来排序建线段树。相邻两个端点之间用数位dp算有奇数个(1)的数的个数,用线段树维护区间并即可。
对于所有(1)到(n)的排列(p),使(i)向(p_i)连边,问期望环的个数
答案即(frac{sum_{i=1}^negin{bmatrix}n\iend{bmatrix}i}{n!}),设(f_n=sum_{i=1}^negin{bmatrix}n\iend{bmatrix}i),则有
不过好像有更简单的方法说明答案就是(sum_{i=1}^nfrac{1}{i})
求一下差分数组,记差分数组中所有小于(-k)的与(-k)的差为(A),大于(k)的与(k)的差为(B),答案就是(max(A,B))
证明比较简单,设(A<B),我们使用(A)的代价把所有小于(-k)的都调整到(-k),使得差分数组只剩下大于(k)的,在用(B-A)的代价把这些调整到(K)即可;由于差分数组的和为(0),这样的调整方案是一定存在的。
10.08
显然当长度为(2^i)的时候最优策略就是一直折半,答案就是(2^i-1);
对于更一般的情况,感性理解一下分成一些(2)的次幂一定是最优的
首先先把必须连的边都连上,如果出环就是(-1);再暴力一下两个点(i,j),看看(i,j)是否能连边,用这些边和必须连的边跑一棵生成树,输出这些边即可。
树是一个(n)个点(n-1)条边的无向连通图,也就是说删除一个点后必须剩下(n-2)条边,且图联通就能保证是一棵树
所以我们删的点必须是度数为(m-(n-1-1)=m-n+2)的非割点,tarjan求一下即可。
发现如果满足(n\%(k-1)=1)的话就是一个(k)叉的哈夫曼树,开一个小根堆,暴力拿出重量前(k)小的合并成一堆即可。又要求最大深度最小,所以额外记一个最大深度作为第二关键字。
当(n\%(k-1) eq 1)时,我们需要确定一个第一次的合并量(i),使得((n-i+1)\%(k-1)=1),显然这个第一次合并量越小越好,我们枚举这个(i),先把这(i)个合并起来;之后再按照(n\%(k-1)=1)的方式合并
我们发现答案就是最大的修改量,于是二分一下这个最大修改量,这样每个数能形成的取值就是一个区间。问题变成了能否给每个数一个取值使得序列单调不降,直接贪心即可。
傻题,讨论一下最大值,无脑分治即可
贪心,感性理解一下我们应该放回去的是下一次出现最晚的那一个,于是用大根堆维护一下。一个坑点是堆中的元素的下一次出现时间必须动态更新,并不需要可删堆,由于新插入的下一次出现时间一定更大,所以直接插入即可。
只会一个无脑做法。我们发现在序列里多次添加同一个数并不会使得前缀(gcd)的变化次数增加,所以这题和UR1的外星人非常相似。
先对于每一个数求一下把这个数放在第一个前缀(gcd)的最大变化次数。之后设(dp_i)表示当前前缀(gcd)为(i)的序列有多少种,我们发现从(i)向(i)的约数(j)转移的时候,会有(left lfloor frac{n}{j} ight floor-left lfloor frac{n}{i} ight floor)个数变得没有作用,所以我们乘上一个排列数让这些数排列进去
更详细的题解还是看看神仙写的吧。更高论的做法好像需要在dp过程中存下(2)和(3)的次幂,过于高论就不会了。
10.09
答案就是行动次数最多的机器人的行动次数,二分这个行动次数(mid)
先所有物品按照重量排序,把这些物品依次加入一个以体积为序的大根堆里,每个有重量限制的机器人贪心地选择质量小于其限制的体积前(mid)大的物品;剩下的物品就只有了体积限制,让有体积限制的机器人贪心选就可以了。
难点在于读题,就是瞎推几下把目标环推出来,之后把初始的环摁在上面匹配就好了。初始环要从两个方向都匹配一遍,否则会WA80
把所有操作倒过来,这样就不用考虑当前操作对一个已经染过染色的格子的影响了,只要使得一个格子仅被访问常数次就能做到(O(n+m))的复杂度,所以使用并查集维护已经染好颜色的格子即可
链接里就是题解
10.10
链接里就是题解
发现这个(x+1,x+2...x+c-1)都出现但(x)和(x+c)不出现不是很好限制,考虑容斥一下,求连续(c-1)个出现-(2 imes)连续(c)个出现+连续(c+1)个出现即可。
考虑离线,把所有询问按照右端点排序,维护当前每种值最靠右的位置,同时维护值域上所有长度为(1)到(c+1)的区间的最小值。每更新一个数,可能影响到的区间就有(c^2)个,我们直接暴力这些区间,并去树状数组上修改这个区间对应的最小值。查询的时候直接查询有多少个长度为(c)的区间最小值不小于(l)即可。据慎老师分析,复杂度只有(O(nc^2+(n+m)log n))
猫哥的走位有点迷,于是先搞个预处理(id[i][j])表示猫在(i),鼠在(j)的时候下一步猫的走位;不难发现因为期望的线性性,我们可以直接搞一个(dp_{i,j})表示猫在(i),鼠在(j)的时候期望走几步,直接记搜转移即可
把题意转化一下大概就是求(f_i=sum_{j}[dep_jleq dep_i]dep_{LCA(i,j)}),考虑先求出所有点和(i)的(LCA)的深度和,再减掉深度比(i)大的。显然深度大于点(i)的点一定在深度和(i)相等的点的子树中,于是我们直接对深度相同的点建虚树,把虚树上每个叶子的点权设为子树大小减1,问题转化成了对于每一个叶子求其他叶子和它形成的(LCA)的深度乘叶子的点权,在虚树上瞎搞一波就行了
10.11
发现这个最低扣成(0)导致不是无法直接算贡献,于是(2^k)枚举一下哪几个部分大零蛋,其余部分照常算,扣成负数也不要紧;显然这样不会使得最优答案变小或一个较小的答案变大。里面套一个(dp_{i,j,k})表示用完第(i)个句子,填了(j)行,第(j)行填了(k)个字的最小扣分。大力转移就好了。
显然这个次大公约数就是(gcd)除以最小质因子,注意到和(a_1)取(gcd)之后一定是(a_1)的约数,所以我们将(a_1)质因数分解,搜出其所有约数,搜的时候就能方便的得到所有约数的最小质因子了
吉老师的小清新(dp),搞了好久搞出一个不一样的做法,题解在链接里
晚上打了场牛客,成功让我知道vector<int> d[maxn]
有多慢,由于卡B卡不过去搞了很久,之后还一边写题一边和瞎颓,导致没有时间去rush一个E,成功4题滚粗+罚时爆炸
10.12
显然是个垃圾题,维护一下每一个质因子最后一次出现的位置,大力离线+树状数组即可
显然是个简单题,大力状压每个点到根的路径上的状态,设(dp_{i,s,j})表示(i)点到根的路径上的状态为(s),子树内部有(j)个农民参战了,贡献直接在叶子节点算好,往上只需要把左右儿子合并一下即可。注意到后两维的状态的乘积始终是(2^n),合并成一维就好了,所以空间复杂度是(O(2^{2n})),再分析一波发现每一层节点对时间复杂度的贡献相同,所以时间复杂度是(O(n2^{2n})),所以难点在于对时间复杂度的分析。
比较玄幻的贪心,注意到我们要最小化的东西是(sum b_it_i-sum A_i),(b_i)是在站点(i)下车的人数,(t_i)是到达站点(i)的时间,(sum A_i)是个定值不用管他。于是最小化(sum b_it_i)即可。
考虑到我们在某一段道路上用一个加速器会使得后面所有的(t_i)都减小(1),所以看起来我们好像是应该在尽量靠前的地方使用加速器。但是注意到有一些车等人的情况,我们发现我们对于一条道路用了加速器,结果后面的某处车停下来等人了,于是并没有使得车等人站点更靠后的站点的到达时间减小。
于是我们分一下段,使得同一段内都是人在等车,每一条道路的价值是同一段里位置更靠后的站点的(b_i)的和,贪心地选出价值最大的一条道路使得这条道路的(d_i)减一即可。之后继续分段,做(k)次之后就是答案了,复杂度是(O(nk))的,loj上有数据加强版看起来非常牛逼的样子。
10.13
如果我们求出来一个叫做(f(i))的东西表示序列的(gcd=i)时( m lcm)的乘积,那么答案就是(prod_{i=1}^mf(i)^i)
大力反演一波
(F(i))表示序列的每个数的取值都是([1,i])时所有( m lcm)的乘积,(g(i)=i^n),每个数的取值都是([1,left lfloor frac{m}{d} ight floor])的时候再乘上一个(d)序列的(gcd)就是(d)或(d)的倍数,这一共有(left lfloor frac{m}{d} ight floor^n)个序列,也一共有(left lfloor frac{m}{d} ight floor^n)个( m lcm),每个( m lcm)都乘上(d)就是真实的( m lcm)
于是问题就变成了怎么求(F(i)),显然很好求我们算一下每个指数次幂的贡献就可以了,复杂度是(O(mlog^2m))
10.14-10.16
打了三天zr的模拟赛,天天被锤爆
10.17
注意到是个( m DAG),于是就先check一下每一条边是否在(1)到(n)的路径上;如果满足(1)到(n)所有路径长度都相等,那么(1)到所有可到(n)的节点的距离都应该相等,设为(d_i),则对于边((u,v))有(1leq d_v-d_uleq 2),跑差分约束即可
题解在链接里
显然地贪心,维护一个后缀最小值,如果后缀最小值小于当前的队尾和队首,那么就加入队尾;否则就让队尾队首里较小的出队
注意到(m-nleq 20),所以我们先求出一棵生成树,不在生成树上的边最多只有(21)条,也就最多(42)个点,我们用这(42)个点构一张完全图,两点之间的距离是连接两点的边权和两点树上距离的最小值,对这张完全图跑一边( m Floyd),每次询问就枚举这张图上的一个点对,统计一下最小值就可以了。复杂度是(O(n+42qlog n+42^2q))
10.18
这题出成这个蛇皮样子显然只能暴力,设(dp_i)表示以(i)为开头的最长倍数子序列,设(f_{i,j})表示(i)后面有多少个转移点(k)满足(dp_k=j),由于最长的子序列是(log)级别的,所以这个数组开的下。在左端插入删除的是否直接枚举一波倍数,右端插入删除就枚举一波约数搞一个类似bfs的东西就好了;预处理约数表的时候并不需要std::vector<int>
,直接连边就非常快
之后就荒废了
10.19
考了个初赛,好像退役了
10.20
下午打了luogu月赛,严重降智啥也不会
10.21
不难发现我们需要有一个位移才能通过反复执行这些操作遍历完整个联通块,于是我们枚举这个位移点,在每个位移点把这个树切开,对这些切出来的树求一个交,答案就是((tot-1-h) imes 2+h),(h)是位移点到根的距离,(tot)是交的大小,复杂度是(O(n^2))
10.22
显然优先满足美观值较大的套娃即可,用std::multiset<int>
查前驱的时候可以直接it=s.lower_bound(x)
再把迭代器--
考虑答案长什么样子,如果最大值和最小值不在端点上,那么区间长度肯定是越短越好;于是我们来个单调队列先算一遍所有长度为(L)的区间的答案,就能包括这种况了;之后是最小值和最大值分别是区间的两个端点,于是我们枚举一个(j)强行将其视为最大值,直接分数规划一波,转化成找到一个(i)满足(Lleq j-i+1leq R)且((a_j-mid imes j)-(a_i-mid imes i)>mid imes k),还是直接单调队列即可
对于一条边((u,v)),能被删除当且仅当存在一个(x)满足(u)能到(x)且(x)能到(v),用std::bitset
维护每个点能到达和能被到达的点集,每次拿出两个bitset
取个与就好了
10.23
断环为链,不难发现答案就是(n-1+min_{i=1}^n{i+max_{j=i}^{i+n-1}T_j-j}),就是枚举一下出发点(i),之后算一下应该在什么时刻出发才能使得走到的所有点的时候都不需要等待,一气呵成地走完
其实枚举(i)点的时候算的并不一定是从(i)出发的最优答案,可能存在一个点(j)出现时间非常晚,最优策略应该是先跳过点(j),先把后面的点取完,绕一圈回来再取(j);用上面的策略算出来的答案显然偏大了,但对于上面的情况,显然从(i)出发并执行最优策略也不可能是全局的最优解,对于上面那种情况,更优的情况应该是从(j)后面的一个点出发,这样就不需要绕一圈回来了
注意到(T_i-i>T_{i+n}-(i+n)),所以我们可以将上面的柿子变成(n-1+min_{i=1}^n{i+max_{j=i}^{2n}T_j-j}),这样就好看多了。
观察这个柿子,只有当(T_j-j)为后缀最大值的时候才能产生贡献,而且产生的贡献就是从前面找到一个最小的(i)满足(max_{k=i}^j T_k-kleq T_j-j),形成的最小值就是(i+T_j-j)
大概是一个类似于单调栈的结构,考虑如何用线段树合并左右区间;可以维护右区间的最值,在左区间上进行二分,找到最后一个大于右区间最值的位置,中间一路记录答案即可
10.24
设(dp_i)表示(i)点子树中能取到的最大排名,(sz_i)表示(i)点子树里叶子节点的个数,当(i)为叶子时显然有(dp_i=1);当(i)上的操作为取(max)的时候,我们(dp_i=max_{i->v}sz_i-sz_v+dp_v),考虑枚举把哪一棵子树的值域分配在最后面;当操作为取(min)的时候,则(dp_i=1+sum_{i->v}dp_v-1),即先给每个子树一段长度为(dp_v-1)的值域,之后再继续分配就只能分配出最小值了
10.26
显然选择的点是直径的一段,如果有一段不在直径上的点那么直径的端点距离这条路径肯定会更远;我们把直径拿出来,对于直径上每一个点求出挂在上面的最长的链,之后单调队列扫一遍所有长度为(m)的区间的最大值就好了,扫出来的最大值记得要跟到直径两端点的距离再取一个(max)
跟上面的题好像没什么区别,换成双指针来扫,同时维护一个单调队列
用上面两道题的方法把直径求出,如果对于一个直径上的一个点(i),其子树中的最长连等于点(i)到直径端点的距离,那么(i)到子树中的最长链这一段也可以成为直径,那么(i)到直径端点上的边就不可能成为被所有直径都经过了,相当于把公共直径给削短了一部分;我们对于直径的两个端点都这样扫一遍,最后剩下的就是公共直径了
把取模拆出来,即求这样一个式子
如果我们能(O(1))做到查询(sum_{i=l}^rb_{x-i imes k})的和,我们就可以整除分块;这里的(k)实际上是(lfloor frac{i}{j}
floor);于是我们根号分治,对于(jleq sqrt{n}),我们直接暴力;对于(j>sqrt{n}),显然有(lfloor frac{i}{j}
floor<sqrt{n}),于是我们提前预处
理一个数组(g[j][i])表示(i)往前跳(j)步的和,就能(O(1))求解一段的信息了,结合整除分块,就能做到(O(nsqrt{n}))的复杂度
10.27
一个结论:一个串和其反串的LCS长度等于其最长回文子序列长度,想想就觉得没啥问题,于是大力区间dp,设(dp_{i,j,k})表示区间(i,j)用了(k)次修改的最长回文子序列,转移大概就是(dp_{i,j,k}=max{dp_{i,j-1,k},dp_{i+1,j,k},dp_{i+1,j-1,k-1}+2}),当(s_i=s_j)的时候,还有(dp_{i,j,k}=dp_{i+1,j-1,k}+2)
10.28
设(f_{n,0/1})表示对于一个区间长度为(n)的线段树,根节点没有/有和其儿子连边的最大匹配个数,同理在记一个方案数;开个map记搜转移就好了,状态数不会超过(2log n)
11.03
刚放完假回来难得有干劲,就写了点题
一个傻傻的(O(n^3))的dp是(dp_{i,j})表示到了(i)个位置搞了(j)个箱子的最小花费,显然这玩意没法继续优化;之后发现我们可以直接把序列倒过来,设(dp_i)表示到了第(i)个位置的最小花费,于是有(dp_i=pre_i+dp_j+max_{k=j+1}^ia_k-min_{k=j+1}^ia_k,pre_i-pre_jleq W),相当于把一个箱子的贡献分开算了;我们发现这个(dp)可以使用单调栈+线段树来优化,于是就做完了
策略比较显然,优先去掉割边,去掉一条割边就会增加一个联通块;之后发现对于一个大小为(L)的话,想增加(i)个联通块需要去掉(i+1)条边,于是把所有环从大到小排序,之后顺着割过去就好了
因为仙人掌上每一个环都是一个点双,所以我们可以大力( m tarjan)找到所有点双,剽了个点双板子,发现挺好背的
普及的题有质量多了,考虑到或和与最后的结果就是一些二进制位相加,于是可以直接枚举两个二进制位(i,j),求有多少条路径满足与在(i)位上是(1),或在(j)位上是(1),把这样的路径条数乘(2^{i+j})累加进答案即可
11.04
把相邻两个金币之间的空位看成石子,发现是一个倒着的阶梯Nim;于是只有奇数层的石子是有用的,我们只算奇数层的情况,偶数层用组合数分配一下就好了;显然一共有(m+1)层,则一共有(lfloor frac{m+1}{2} floor)个奇数层
先手必败的条件是异或和位(0),即每一位上都是偶数个(1);于是我们可以按位考虑,设(f_{i,j})表示奇数层从分配了(i)颗石子,已经考虑完了第(j)位,我们枚举当前这一位上所有多少个(1),用组合数把这些(1)分进去就好了,即(f_{i,j}=sum_{k=0}inom{lfloor frac{m+1}{2} floor}{2k} imes f_{i-2^i imes 2k,j-1}),直接暴力转移即可;复杂度是(O(nmlog n))
设(dp_{i,j})表示把(s)的前缀(i)分成(j)段最多能匹配到(t)串的位置;转移有两种,一是(s_{i+1})不选,即(dp_{i,j})向(dp_{i+1,j})转移;还有一种是(s_{i+1})选,显然我们应该尽可能地往长里匹配,设(l= m LCP(s_{i+1},t_{f_{i,j}+1})),即(dp_{i,j}+l)向(dp_{i+l,j+1})转移
11.05
设(dp_{i,j})表示插入了前(i)种颜色,有(j)对相邻的且颜色相同的格子;对于当前要插入的颜色(i),我们发现把其分成(k)段,内部形成的相邻相同颜色对数就是(c_i-k);如果之前形成的对数为(j),把(i)颜色分成(k)段,我们枚举一下其中(p)段插入到那(j)段相邻且颜色相同格子之间,那么新的对数就是(j+c_i-k-p),从(j)对里选(p)个,再从剩下的(n+1-j)个空位之间选(k-p)个,把(c_i)中颜色分成(k)段,这要乘上一堆组合数,大概是(inom{j}{p} imes inom{n+1-j}{k-p} imes inom{c_i-1}{k-1})
11.06
根号分治一下;对于(ileq sqrt{n})的物品,这显然是一个多重背包,设(f_{i,j})表示前(i)个物品选的体积为(j)的方案,(f_{i,j}=sum_{k=1}^if_{i-1,j-k imes i}),我们发现这个东西放到(mod i)意义下能前缀和优化,于是这边的复杂度是(O(nsqrt{n}))
注意到对于(i>sqrt{n})的物品来说,数量限制其实没有用的,等价于一个完全背包;由于物品的体积都大于(sqrt{n}),所以背包中的物品个数不会超过(sqrt{n})件,设(g_{i,j})表示背包中有(i)件物品体积为(j),我们有两种操作,一种是加入一个体积为(sqrt{n}+1)的物品,一种是所有物品题积加(1),不难发现我们通过这两种操作能构造出所有符合条件的状态,于是有(g_{i,j}=g_{i-1,j-sqrt{n}-1}+g_{i,j-i}),这边的复杂度也是(O(nsqrt{n}))
11.09
计数转一下概率,视为每次操作等概率发生,即求极长连续段个数的期望乘上(2^i)即可
考虑对于一个给定的情况,如何计算极长连续段数目,可以在每个极长连续段开始的时候计算贡献,即(1+sum_{i=2}^n[a_{i} eq a_{i-1}]),于是设(f_i)表示(a_{i} eq a_{i-1})的概率,我们要求的即(1+sum_{i=2}^nf_i);考虑对于一个修改操作([l,r]),如果发生,那么(r+1)和(l)肯定和上一个数不一样了,于是(f_{l}=frac{1+f_{l}}{2},f_{r+1}=frac{1+f_{r+1}}{2});对于(iin [l+1,r]),如果这次操作发生那么(a_i)就会等于(a_{i-1}),于是有(f_i=frac{f_{i}}{2})。于是直接暴力过去就能做了
先跑个tarjan缩一下强联通,对于一个强联通分量,我们记下这个强联通分量里的最大边权和最小边权;搞一个拓扑求一下(1)号点到所有强联通分量的最大边权和最小边权;答案是一个极差,所以讨论一下最大值和最小值来自哪里,最大值和最小值来自强联通分量内部都很好算;考虑最大值和最小值都来自(1)到这个强联通分量(v)路径上的情况,现在有一个和(v)直接连边的(x)要向(v)转移,如果最大值和最小值都在(1)到(x)的路径上,那么我们直接让(v)继承(x)的答案就好了;也有可能(x)到(v)这条边的成为了新的最大值或最小值,还是拿(x)的最值讨论一下就好了
转移大概是这么写
dp[v]=max(dp[v],dp[x]);
dp[v]=max(dp[v],max(max(dp_mx[x],e[j].w),mx[v])-min(e[j].w,mn[v]));
dp[v]=max(dp[v],max(e[j].w,mx[v])-min(min(dp_mn[x],e[j].w),mn[v]));
11.10
观察一波发现肯定是(a)序列中的连续一段对应了(b)序列中的一个位置,且这些对应关系两两不交;比如一个(a)序列1 0 1 0 1
一个(b)序列2 0 1 0 0
就是1 0 1
对应了2
,0 1
对应了1
;对应关系不相交也是比较显然的,因为相交的对应关系根本没有办法合并过去;于是我们存一下(b)中的非(0)位置,之后扫(a)序列,一旦扫到一段和等于(b)中那个待匹配的数,就匹配过去,如果位置相等就不需要花费代价,否则就要花费(1)的代价
由于边权都是(2^i),所以最短路需要最小化最大边权,最小化次大边权......于是这就是一棵最小生成树,建出树来求个lca就没了
随便推一波式子发现答案就是(frac{1}{4}sum_{i=1}^n a_i imes (frac{3}{4})^{i-1}),这里的(a)是从大到小排好序的序列,于是随便用线段树什么的维护一下就好了
考虑一个暴力,我们用小根堆维护目前前(k-1)大的数,每加进来一个数就把堆顶弹出去插入新序列的末尾,这样的复杂度是(O(ans imes nlog n))
考虑这个暴力的一些性质,发现对于一个数(a_i),如果前面比它大的数不超过(k-1)个,那么这些数都会被移动到他后面去;否则就只能移动(k-1)个,设(b_i)表示(i)前面大于(a_i)的数的个数,答案就是(lceil frac{max b_i}{k-1} ceil)
对于一个点(i),我们将其换到(x)的位置上,发现点权变成了(a_i-dep_i+dep_x),于是我们定义(b_i=a_i-dep_i),现在我们要做的就是把这些点权分配到树上,使得每个点点权+深度不小于子树内点权+深度
首先对于根节点,我们肯定要分配点权最大的点,如果点权最大的点有多个,那么我们把哪一个放到子树中都会使得它比根更大,所以无解;之后考虑一条链的特殊情况,我们发现,如果有两个点权相等的点,那么无论哪个点在下都会大于在上面的点,于是也无解;扩展到多条链,我们发现点权相等的点不能超过支链个数,否则一定会出现两个点权相等的点成为祖先关系,于是只需要判断点权相等的点和支链的大小关系即可
11.12
如果输入的两个编号中较大的那个不是(n),那么就直接GG了;否则,我们考虑把(n)作为根,之后瞎构造;不难发现构造一条链一定是最优的,于是直接莽过去就没了
求一下直径,显然我们应该尽量留着直径的两个端点,优先删挂在侧链上的叶子;把侧链删完之后在删掉直径就好了
把边和询问都排序之后离线,维护每个联通块大小的平方和就好了
用权值线段树维护修改,每次在权值线段树上二分找到最后一个(ih_i-sum_{j=1}^ih_jleq v)的位置就好了