【GDOI2018】所有题目和解题报告
使用说明:题意和数据范围都只是回忆内容,仅供参考。题解陆续补上。
Day 1
第一题
题意:给定n个数字,要求划分成k的连续段使得每个连续段内的数字之和相同,求最大的k。n,Σai<=10^6。
算法:模拟
题解一:记sum=Σai,从大到小枚举sum的因子暴力O(n)判断,10^6范围内的因子个数至多200~300个,且数据无法构造卡到上限(中途退出),可以轻松通过。
题解二:统计所有前缀和记录到同数组b[]中(即b[i]表示存在大小为i的前缀和),从大到小枚举sum的因子x后,计算每一个k*sum/x(1<=k<=x)在b[]中是否出现即可。复杂度O(\(\sigma_1(sum)\)),其中\(\sigma_1(sum)\)表示sum的约数和。
第二题
题意:给定n个0~m-1的数字,每次操作可以在模m意义区间+1或区间-1,求最少几次操作可以使所有数字变成0。n,m<=10^5。
算法:差分+贪心
题解:如果不考虑模m意义就是一道经典题目。差分后区间操作变成一次+1和-1。差分后实际上有n+1个数字,而第n+1个数字可以任意改变。那么差分后正数之和为A,负数之和为B,那么ans=max{A,B}。
现在考虑模m意义,把所有数字转化为非负数,要选择一些数字变成0,另一些数字变成m。为了使答案尽可能小,变成0一定优先选小,变成m一定优先选大,所以排序后贪心从两边取维护A和B的平衡即可(也可以枚举分界点。
复杂度O(n)。
第三题
题意:给定n个点的带点权树,每天早上根的数字变成0,每天下午每个点的数字往根移动,每天晚上会有一些单点加值的操作。给定m个操作,每个操作在第ai天晚上在点bi加上数字ci。给定k个询问,每次询问第ai天凌晨的【以bi为根的子树】的数字和。n,m,k<=10^5。
算法:CDQ分治 或 树套树
题解:先不考虑修改操作,对每个点x记深度d[x],dfs序入栈序in[x]和出栈序out[x]。一个点x会在询问(ai,bi)中被统计当且仅当满足\(d_x \leq a_i\)且\(in_{b_i} \leq in_x \leq out_{b_i}\)。关键在于把子树看成dfs序后,这就是个二维偏序问题了。
对于修改操作(ai,bi,ci),将深度维改为深度+时间维,所有初始节点时间默认为0,修改就在bi下面接一个时间为ai权值为ci的点即可。
但是这样还有一个问题,就是由于离线操作,时间靠前的询问可能统计到时间靠后的询问(因为深度和时间加起来计算了),所以需要再加一个时间维。
这样就是三维偏序问题,用CDQ分治解决,复杂度\(O(n log^2n)\)。
第四题
题意:给定n个点的竞赛图,m条已知的点不相交简单路径,其余边方向随机,求形成强连通分量个数的期望。
算法:
Day 2
第一题
题意:给定n个点m条边的无向图,第i个点有权值ai,边(x,y)的权值定义为:
可以选择一个数字p,使得所有边的权值都减少p(至多减到0),给出限定值T,求最小的p满足1~n的最短路<=T。
n,m<=20000,ai<=105,T<=1018。
算法:莫比乌斯反演+二分最短路
题解:对于两点权值为a,b的边权w:
莫比乌斯反演易得:
后面部分直接计算:
复杂度\(O(m \sqrt{a_i})\)。
预处理所有边权,二分p计算最短路判断即可。最短路数组记得初始化为比1e18大的数字。
第二题
题意:给定n个点的树,定义f(S)为点集S的导出子图的边数,求\(\sum_{S}f(S)^k\)。n<=10^5,k<=10。
第三题
题意:给定n个二元组(xi,yi),两个二元组i和j的价值定义为\(|x_i-x_j|*max\{y_i,y_j\}\),一个区间[L,R]的价值是其中任选两个二元组的最大价值。
给定m个操作,修改一个二元组的x或y,询问一个区间的价值。
n,m<=10^5。
数据保证初始的y和修改的y随机生成。
第四题
题意:给定n个点的无向图邻接正边权矩阵。每个点可能正在维修(不可经过)。k次操作,询问点x出发回到x的最短路径,或改变一个点的维修状态。n,k<=400。
算法:dijkstra
题解:T4也出走路题,想不到吧!
从点x出发回到x的最短路径就是最短简单环。
每次询问将点x删除后将与点x有直接连边的点标记为关键点,那么就是求解关键点两点间最短路的最小值。(与x的连边边权只要在最短路初始值设置的时候修改即可)
解决这个问题,将关键点作为起点集进行dijkstra,访问到一个点的最短路(第一次访问)和次短路(第二次访问)加起来就是这个点对答案的贡献,取最小值就是答案。
修改操作是假的。
Day 3
第一题
题意:给定n个人的三元组(ai,bi,ci),一个人能打败另一个人当且仅当至少有两个属性大于另一个人,数据保证没有两个人的同一个属性相同。
共进行n-1轮游戏,每轮任选两个人淘汰败者,求哪些人可能成为最后留下的人。n<=10^5。
算法:主席树+Tarjan缩点。
题解:朴素做法是暴力求出两两有向边的方向,然后对竞赛图缩点后有一条哈密顿路径,唯一那个入度为0的强连通分量包含的点数就是答案。
证明比较显然,①有入度的强连通分量一定不可能淘汰掉入度到它的强连通分量,②入度为0的强连通分量一定有哈密顿回路(竞赛图的性质),故让其中某个点x留到最后只需要从它上一个点开始往前一直两两淘汰,最终就会剩下x的下一个点。
现在的问题是边数太多了,但有很多冗余边。假设只有a,b,那么所有店按a排序后以b为下标建主席树(可持久化权值线段树),每次父亲向儿子连边以及新链叶子向依赖链叶子连边,然后每次的点向直接引用依赖链的左子树连边,这样建图后连通关系就完全等价于上面的建图了。建三棵主席树ab,ac,bc连边即可。
复杂度O(n log n)。
第二题
题意:给定n个点构成的完全二叉树,即点n的父亲是点\(\frac{n}{2}\),边权为\(an^2+bn+c\),其中a,b,c为给定的常数。有m次删除以某个点x为根的子树(可能重复删除),每次删除后要求找一个点x,满足所有点到它的距离和最短,求点x和距离和。n,m<=105,a,b,c<=109。
第三题
题意:给定V个点E条边的无向图,有一个长度为n的小写字母串,有m只猴子各自携带一个子串要从1到V,两只猴子的路径如果有边相交那么会发生强度为两个子串的LCP的叫嚣。要求安排所有猴子的路径使得所有叫嚣的最小值最大。V,E<=10000,n,m<=10^5,保证80%的边直接从1到V。
算法:最大流+二分哈希
题解:首先如果知道有k条边不相交的路径可以从1到V,那么二分叫嚣值L,如果两个子串的LCP>=L那么它们可以在同一条路径上,而且LCP>=L的性质有传递性,所以直接用桶记录每个子串长度为L的前缀就可以知道至少需要多少条路径,判断是否>k即可。
如何知道从1到V有多少条边不相交的路径?将所有边转化为流量为1的边,跑最大流就是答案。
第四题
题意:对一个黑白格图进行大模拟得到一棵带点权树,求树的直径(点权和)长度为x,然后要求将x划分成若干个整数的方案数之和。n<=10^5。
复杂度\(O(n \sqrt n)\)。