最后一天了。
T1
题目大意:定义一个区间的值为其众数出现的次数,给出n个数,求将所有区间的值排序后,第K大的值为多少。n<=1e5。
题解:
二分答案t,统计众数出现次数大于等于t的区间有多少个。
枚举右端点R,计算左端点L最大为多少,使得区间[L,R]的值大于等于t,对于每个R他对答案贡献为L。
通过线性扫一遍找出每一个数的前面第t-1个与他相同的数字,记其位置为b[i],若不存在则为0。
若R增加,则[L,R+1]的值也必定大于等于t,所以新的L=max(L,b[R+1]),这样就可以找出每一个R对应的L,计算出答案。
T2
题目大意:n个节点,选择每一个节点有代价,m个区间,区间内所有点都被选择有收益,令收益-代价最大。n,m<=2e5。
题解:
定义dp[i][j](1<=i<=j)表示当前考虑到第j个点时,刚好取了[i,j]这一段区间的点,所能得到的最大价值。
定义a[j]表示当前考虑到第j个点时,不选择第j个点,所能得到的最大价值。
状态转移方程如下:
a[j]=max(dp[1][j-1],dp[2][j-1]...dp[j-1][j-1],a[j-1]); dp[j][j]=a[j-1]-cost[j]; dp[i][j]=dp[i][j-1]-cost[j]; (i<j).
如果有一段区间[L,R]的回报是W,则 dp[L][R]+=W, dp[L-1][R]+=W.... dp[1][R]+=W;
注意到状态转移的特性,所以可以用线段树来优化DP。
将线段树的叶子节点当作dp方程的第一维,那么以上即可变为区间加减,区间询问最值。
T3
题目大意:定义一个数是楼梯数字,当且仅当这个数的每一位数字不小于它的下一位数字。求有多少个长度恰好为n的楼梯数字,是k的倍数。由于数量很大,输出Mod 1000000007的结果。n<=1e8,k<=500。
题解:
楼梯数字可以拆成不超过 9 个全一数字的和,这些数字在模 K 意义下的值有 O(K) 种取值,可以将这些数分成 O(K) 组,进行分组背包计数。
令 f[i][j][k]表示前 i 组里选 j 个数的和在模 K 意义下是 k 的方案数,由于同一组里选 m 个数组成可重集的方案数是C(X−1+m,m),其中 X表示组里不同数字的个数,所以转移是枚举当前组里选多少个数进行转移。
注意 10^(N−1) /9至少要选1个,所以将它从上面的计数里排除,最后枚举它的数量,再配合之前计数的结果进行计数即可。
T4
题目大意:给定一棵n个点的树,以及m条路径,定义f(i,j)为第i条到第j条路径的交集部分的长度,求Σf(i,j)。n<=5e5。
题解:
考虑一条边会在多少个f(i,j)中被计算
当一条边断开后形成的两部分中,每个部分都含有一个第i~j条路径的端点,则f(i,j)中会包含这条边
所以可以枚举边后,计算其子树中有多少个f(i,j)符合条件,即第i~j条路径都有且仅有一个路径端点在该子树中
可以用函数式线段树来维护每棵子树的信息,对于表示点u子树的线段树,可以通过所有点u的儿子节点v的线段树合并得来