( m THUSC)
(T1)
题意:
给定一个长度为 (n) 的序列 (a) 和一个正整数 (m) ,现在按下述策略删除 (a) 中的数字:
选出一个下标序列 (p) ,使得其:
元素个数最多;字典序是满足上述条件的序列中最大的。
然后删除 (a) 中下标在 (p) 中的元素。问按上述策略进行几次删除会使 (a) 为空。
(nle 5 imes 10^4, mle 10^9)
做法:
直接二分之后,问题转化成:查询一个后缀前 (k) 大的权值和,删除元素。这是树套树的模板题。
(T2)
题意:
给你一颗带点权树,要选一个点集使得它是一条链,并且按照链的顺序 , 点权序列是最长上升子序列,最大化最长上升子序列长度。
(nle 10^5)
做法:
直接点分治可以做到两个 (log)。考虑一个 (log) 的做法。
设 (f[i][j]) 表示考虑到 (i) 为根的子树,子树内权值为 (j) 的向下最长上升子序列的最大值。
这个可以直接采用线段树合并维护,考虑怎么计算答案,合并的时候直接记录右半部分最大值之类的可以做到一个 (log)。
(T3)
题意:
有 (n) 个人和 (m) 种菜 , 第 (i) 个人对第 (j) 道菜的喜爱程度为 (a_{i,j}),如果 (a_{i,j} = -1)则表示不喜欢。
现在你要选择一个菜的集合,你会获得喜欢集合中所有菜的人对这些菜的喜爱程度之和的权值,最大化这个权值。
(nle 20, mle 10^6)
做法:
枚举那些人最后会对答案产生贡献,那么最后的答案就是所有产生贡献的人的喜欢的菜的并集的所有喜欢度之和,直接做复杂度 (O(2^nnm))。
不难发现,枚举人的集合之后,我们要求的就是所有人都喜欢的菜的集合的贡献和。对于每个菜,记录其对应每个人的二进制位,枚举一个菜的集合,也就是相当于一个高维后缀和的过程。当然做完高维后缀和之后,每一位要减去所有 (0) 位置的贡献,也就是对于一个人的集合 (S),我们需要减去其超集所有比他多的部分的和,再做一次高位后缀和即可。
第一次:(x^S=sum_{iin S}a_{i, j}),第二次:(x^{S-2^i}=a_{i, j})。
(T4)
题意:
(m) 测,要求实现对一棵有 (n) 个节点,儿子有顺序的无标号树的编码和解码,只能用一个 (int128)。(n≤70,m≤10^5)
做法:
由于儿子有顺序且无标号,那么这棵树对应的括号序列是唯一的,括号序列的方案数是卡特兰数,我们又知道首尾一定是匹配的左右括号且 (Cat_{69}<2^{128}),那么我们只需要完成对卡特兰数的 (Hash) 即可。
至于标号,直接按照字典序即可。只需要 (dp) 出当前前缀和位 (i),用了 (j) 位的方案数即可。
( m PKUSC)
(D1T1)
题意:
有一个 (n imes n) 的矩阵,重复 (k) 次,每次同时把 (a_{i,j})赋值为 (i) 这⾏的和加上 (j) 这列的和,注意 到 (a_{i,j})自己的贡献是算两遍的。
求出 (k) 次变化后的矩阵对一个模数 (p) (不一定是质数)取模的结果。
(nle 10^3, kle 10^9)
做法:
推一推贡献即可发现,对于 ((i, j)) 来说,我们把所有点分成四类:((i, j), (i, y)(y e j), (x, j)(x e i), (x, y)(x e i, y e j)),这四类的贡献都是相同的而且很好统计,直接统计即可。
(D1T2)
题意:
初始有一个长度为 (n) 的序列 ,每次给定区间 ([l,r]) 并执行以下两种操作之一:
- 令 (i) 从 (L) 循环到 (R-1) ,将 (a_i)赋值为 (max(a_i,a_{i+1}))
- 查询 ([l,r]) 从左往右前缀 (max) 单调栈元素之和。
(nle 3 imes 10^5)
做法:
考虑建树,将每个点连向其后第一个比他大的点,那么答案可以表示成一条直上直下的链。
考虑对于每个点,我们维护一个 (b[i]),表示修改后的 (a[i]'=max(a[i], a[i + 1], …, a[b[i]]))。考虑到 (b[i]) 一定是单调递增的,每次修改 ([l, r]) 实际上表示的是将 (l) 的 (b[l]) 删除,再将 (b[l + 1…r]) 左移一位,然后令 (b[r]=b[r-1])。
考虑令 (c[i] = max(a_{b_{i-1}+1}, …, a_{b_i})),然后答案可以等价于开头为 (x=max(a_{i}, …, a_{b_i})) ,从 (c[l]) 到 (c[r]) 的答案。
不难发现,每次修改 ({c}) 序列只会进行单点修改,每次相当于把一个数删掉,我们要求的实际上是一条链上没被删除的点的个数,只需要进行链修改和链查询即可。
(D1T3)
题意:
九条可怜开始打德州扑克。
做法:
此非碳基生物可做也。
(D2T1)
题意:
给定一颗树,你需要删除一条边,再增加一条边,使得原图仍然为一棵树,问所有方案的 (sum_{i=1}^nsum_{j=i+1}^ndis(i,j))
(nle 10^6)
做法:
考虑删除一条边之后答案减少量,再考虑增加一条边之后答案增加量,然后直接利用换根 (dp) 统计即可,复杂度 (O(N))。
(D2T2)
题意:
有 (n) 个物品,第 (i) 个价值为 (a_i),有一种代金券,如果花了 (c) 块钱就给你一张代金券 你可以用一张代金券来换一块钱,注意换出来的钱是不可以继续参与代金券的兑换的。
也就是你可以用掉 (b) 张代金券(前提是你有 (b) 张),再花 (a_i-b) 元,拿到 (lfloor frac{a_i-b}{c} floor) 张代金券。 有 (q) 次单点修改,每次改完你都要求出,当前按顺序购买最少花的钱数。
(q, nle 3 imes 10^5, a_i, cle 10^{12})
做法:
先考虑 (O(qN)) 怎么做。首先一个显然的观察是,我们将每个数 (x) 拆分成 (x-x\%c, x\%c)。那么我们的贪心策略一定是:如果有代金券,就优先消掉 (x\%c) 部分,然后用现金购买 (x-x\%c) 部分。最后存在一个分界点,在之后的所有点我们都可以用代金券购买。
假设后缀和数组为 (b[i]),在当前分界点时代金券数量为 (n),那么分界点 (x) 应该满足:(b[x]>nge b[x+1])。
找到分界点之后,我们用假设我们用 (m) 张代金券,那么我们需要满足 (n-m+lfloordfrac{a[x]-m}{c} floorge b[x+1]),可以通过二分解出 (m),那么我们已经得到了一个 (O(qN)) 的做法。
显然分界点是可以二分的,因为 (n) 的变化量一定小于 (b) 的变化量,我们只需要知道用了多少张代金券即可求出答案。因此我们只需要维护出,后缀和,到每个点时代金券的数量,以及到每个点时已经用了多少代金券。然后再采用线段树二分即可求解。
后缀和是很好维护的,我们只需要考虑到每个点时用了多少代金券以及还剩下多少代金券即可。而这两者的总和是确定的,所以我们只需要维护一者即可。
设 (d[i]=lfloordfrac{a[i]}{c} floor, e[i] = a[i]\%c),那么我们只要找到 (min(sum d[i]-sum e[i])),在这个点的时候代金券数量为 (0),然后之后代金券数就是 (sum d[i]-e[i]) 了,所以在点 (x) 的代金券数实际上是 ((sum_{i=1}^xd[i]-e[i])-min_{j=1}^i(sum_{k=1}^j d[k]-sum_{k=1}^j e[k])),这些都是很好维护的,于是我们可以在 (O(nlogn)) 的复杂度内解决问题。
(D2T3)
题意:
有 (n) 个 ([0,m]) 的随机变量,求满足以下条件的概率:任何⼀个长度为 (k) 的区间内包含的随机变量不超过 (2) 个。
(kle mle 150, nle 50)
做法:
首先可以小数部分的相对大小,为 (O(n!)),将 (m) 个点拆分成 (nm) 个点,然后对于每一种方案,设 (f[i][j][k]) 表示考虑到第 (i) 个人,上两个选择的点分别是 (j, k) 的概率。然后直接转移即可。
考虑这个枚举阶乘是不需要的,因为每个人是无序的,可以修改成设 (f[x][i][j][k][l]) 表示考虑到第 (x) 个点,前两个点的整数部分分别是 (i, j),然后前两个点在 前 (x) 个点中的小数部分排名分别是 (k, l),考虑新增一个点,先枚举其整数部分,再枚举其插入到那个小数部分后面,状态数是 (O(n^3m^2)) 的,转移可以采用前缀和优化。复杂度 (O(n^3m^2))。
我们发现当 (i, j) 距离超过 (k) 的话,那么这个状态无用,所以我们的状态数实际上是 (O(n^3mk)),考虑到当 (m<nk) 时,答案一定是 (0),所以总状态实际上是 (O(n^2m^2)) 的,同样采用前缀和优化可以做到 (O(n^2m^2))。