A 最短路 dp
赛中直接每次询问暴力Dijkstra,$O(qn\log n)$就能过,属于是CF神机太快了。
正解应该是dp,用$f_{c,i,j}$表示经过了$c$条边($c+1$个点)后,$i$到$j$的最短距离,于是有转移
因此每次可以在$O(nm)$时间内处理出经过$c$个点的最短路,此时再$O(q)$更新所有询问的答案,对于询问$q(u,v,x)$,答案即为$min(f_{c,u,v}+c\times x)$,总复杂度$O(n^2m+nq)$。也就只比暴力快了400ms
1 |
|
B 签到
阅读理解,看懂题目所给公式就会了。
如果要让结果最大,就要选取所有权值为奇数的边,因此答案就是所有奇边权之积,注意没有奇数边权输出$1$。
1 |
|
C kmp
题意即求所有子串的最长公共前后缀长度之和。
由于$length\le5000$,对于所有起始位置跑一遍kmp,得到的next数组(前缀函数)就是最长公共前后缀,求和即可。
1 |
|
D 模拟
纯模拟,建议写个函数单独提出x前后的数字,用map记录次数相同的项,求导就是$(ax^b)’=abx^{b-1}$。注意当求导后没有任何项的时候要输出0。
1 |
|
E 构造
原问题等价于给树上的每条边确定一个方向使得有最多的边满足入度=出度(称其为平衡),其拓扑序即为答案。
首先如果一个点的度为奇数显然不可能平衡,那么我们只需要考虑使度数为偶的点平衡。
先只考虑所有度数为偶数的点组成的图$G’$,一个显然的结论是,只要这张图所有点的入/出度都不大于其度数的一半,则所有点一定能被平衡(用度数为奇数的点调整),所以怎么舒服怎么写就可以了。
1 |
|
F adhoc
考虑把原来的操作2转化一下。可以发现,操作2等价于把矩阵的最后一列往下,然后整列插到第一列前面。
因此我们可以记录一下哪里是当前矩阵的最后一列,每次操作2不做实质上的移动,只维护最后一列的位置,然后$O(n)$将最后一列往下移动。注意此时操作1也要根据最后一列的位置调整修改的坐标。
1 |
|
G 重链剖分 线段树
一道比较直球的数据结构题,给一棵带点权的树,需要支持:
- 询问任意两点路径上的权值和
- 对任意子树增加一个关于深度的等差数列
涉及动态子树加+维护树上路径和,显然得套个重链剖分,假设我们能用线段树维护每条链的结果,这样1就解决了。
考虑2操作在一条链上如何维护,即如何在数组上实现区间加等差数列+询问区间和。可以发现等差数列是可以合并的,我们可以将加在$i\in[l,r]$上的等差数列$s+(i-l)\times d$移动一下,转化为$(s-l\times d)+(i\times d)$,如此我们就能把整个数组分成两部分信息维护(设其为$a$和$b$)并且预处理出线段树上每个区间的$\sum i$,每次区间加操作时,对于当前节点就有$a+=(s-l\times d),\ b+=(\sum i)\times d$。
转换到树上,就相当于把上面的$i$全都改成$i$节点的深度。dfs序建线段树然后维护等差数列拆出来的两部分,每次询问$(u,v)$再拆成$query(v)+query(u)-2\times query(lca(u,v))+w_{lca(u,v)}$,$query(u)$表示从$u$到根的路径和,处理时直接暴力往根跳最多$\log$条链到根,每次在线段树上询问一段连续dfs序的和。总复杂度$O(n\log^2 n)$。
会爆ll,要用__int128
写起来真的恶心 都算得上是大模拟了
1 |
|
H 数学
由于数据范围较小,可以直接模拟,从头开始到$t$时刻每次找到$C$和$A,B$相交的时间,注意处理$B$恰好到达$d$而第三个人从$A$前往$B$处的情况(因为这个到结束都没改出来)。本题不卡精度,很良心。
1 |
|
I 网络流
1 |
J 计算几何
牛逼防AK计算几何,扔了。
K 树状数组
题意就是求对于所有红点求出其到最近的蓝点的曼哈顿距离之和。
考虑两点曼哈顿距离的公式$|x_1-x_2|+|y_1+y_2|$,实际上拆开绝对值符号一共有四种情况,以$x_1-x_2+y_1-y_2$为例:
我们先按照$x$坐标排序,枚举$x_1$同时用树状数组维护下标为$y_2$时的贡献($-y_2-x_2$),因为是按$x$升序排序,可以保证$x_1\le x_2$,在树状数组上查询所有不大于$y_1$的点中的最小值更新答案即可。对于其他拆绝对值的方式,实际上可以将所有点绕原点旋转90度然后复用上面的方法。
(拆绝对值的四种情况对应到图象上就是$2$相对$1$的四个象限)
1 |
|
L dp
注意到我们每次操作选取的点集可以为空,因此只要用最少的代价将这棵树调整为堆即可。
如果每次操作可以加上任意的正值,我们就可以从根dfs,每次如果当前节点小于其子树中的最大值,就要将其调整到这个值,设其差为$\Delta$。
考虑到每次加的值$x_i$是给定的,所以在调整子树的时候要用所给$x_i$组成尽可能小的合法值(即不小于$\Delta$的最小值),这就是经典背包问题了,$f_i=1/0 $表示用所给$x_i$能/否恰好组成$i$,扔到$set$里每次加的时候二分。
由于$\sum x_i\le10^6,q\le10^3$,需要跑$10^9$次,因此考虑经典$bitset$优化01背包,时间复杂度$O(\frac{10^{9}}{\omega}+n)$。
1 |
|
M 贪心
问题转化成往图中加边$e(i,b_i)$使得整张图是个长为$n$的环且数组$b$和$a$最接近(要在和$a$的$LCP$尽量大的前提下字典序最小)。
由于要和$a$尽可能相似,我们就从头开始令$b_i=a_i$,同时将$e(i,a_i)$插入原图,用并查集维护连通性。当遇到加入$a_x$时和之前的成小于$n$的环或者$a_x$在以前出现过时,停止插入$a$序列。此时维护图中所有点数大于$1$的链,从小到大遍历$[x,n]$,每次贪心的将$i$连向最小的可以连的链尾(即为$b_i$),同时更新链尾,直到所有数都在一个长为$n$的环上。时间复杂度$O(n\log n)$。
1 |
|