ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF DS题做题笔记(持续更新)

2022-06-12 10:34:42  阅读:148  来源: 互联网

标签:10 le 复杂度 CF 异或 做题 权值 DS 边权


CF DS题做题笔记(持续更新)

题目来源:Codeforces 的 problemset内,difficulty 2300-2600,并包含“data structures”的 tag。

1681F

题意:给定一棵树,边有边权 \(w_i\),定义 \(f(u,v)\) 为,\(u,v\) 路径上只出现一次的权值个数,求 \(\sum_{1\le u < v \le n} f(u,v)\),\(1 \le n,w_i \le 5 \times 10^5\)。


分析:考虑求出每种边权对答案的贡献,将某条权值为 \(w\) 的边放到中间(图中标记的边权值为 \(w\),其余均不为 \(w\))。

将 \(<6,7>\) 放在中间。

1687F P1

考虑能使 \(<6,7>\) 产生贡献的路径个数。

显然,路径的一端要在 \(\{1,3,4,6\}\) 里面选择,另一端在 \(\{7,9\}\) 里面选择,可以理解为那些其他同权值的边把树断开了。

如果将所有权值为 \(w\) 的边删除,那么某一条权值为 \(w\) 的边对答案的贡献为两端连通块大小的乘积。

直接做时间复杂度为 \(O(n^2)\),考虑基于值域分治。

定义 \(solve(l,r)\) 为,求解所有 \(w_i \in [l,r]\) 的边的贡献和,我们可以先将 \(w_i \in [l,mid]\) 的所有边加入并查集,然后调用 \(solve(mid+1,r)\),结束后将 \(w_i \in [l,mid]\) 的所有边撤销,加入 \(w_i \in [mid+1,r]\) 的所有边,并调用 \(solve(l,mid)\),当 \(l=r\) 时,只有一种权值的边没有加入,在并查集上查询求解即可。

由于并查集要可撤销,故不能路径压缩,运用按秩合并保证复杂度,总复杂度为 \(O(n \log^2 n)\)。

此外这题可以用 LCT 求解,枚举到某一个权值,先将对应的边删除,求解,再加入,LCT 中维护树的大小即可,复杂度 \(O(n \log n)\)。


1625D

题意:给定 \(n\) 个整数,\(a_1,a_2,...,a_n\),并给定一个整数 \(k\),求出一个最大的集合 \(S\),满足 \(S\) 中的元素均 \(\le n\),且对于任意两个 \(S\) 中的元素 \(x,y\),满足两数异或和 \(\ge k\),\(1 \le n \le 3 \times 10^5,0 \le a_i,k \le 2^{30}-1\)。


分析:如果两个数异或结果的最高位比 \(k\) 大,则异或结果一定 \(>k\),定义 \(f(x)\) 表示当 \(x\) 不含有前导 \(0\) 的情况下二进制位数,考虑将所有数,在二进制表示中的末尾去掉 \(f(k)\) 位,并按新的数分组,若两个数处于不同组,则它们异或和一定 \(>k\)。

对每一组分别求解,容易发现每一组最多只能选上 \(2\) 个数,如果选 \(\ge 3\) 个数,就一定存在两个数,它们异或和 \(<k\),因为 \(k\) 的最高位上的数字一定会有 \(2\) 个 \(0\) 或 \(2\) 个 \(1\)。

设目前处理的那一组的数为 \(b_1,b_2,...,b_m\),即要求出是否存在两个数满足异或和 \(\ge k\),即求两个数最大异或和。将数转化为二进制,依次插入 trie 中,并查询最大异或和,即每次尽量往自己相反的方向走。

注意每一组求解完成后要清空 trie,不能 memset,要一个一个删除。

时间复杂度 \(O(n \log A)\)。


1575I

题意:给定一棵树,点有点权 \(a_i\),两点 \(x,y\) 之间边的长度定义为 \(\max\{|a_x+a_y|,|a_x-a_y|\}\),其中 \(|k|\) 表示 \(k\) 的绝对值,有两种操作,一种是修改某个点的点权,另一种是查询两点间简单路径的长度,\(1 \le n,q \le 10^5,0 \le |a_i|,|a_i^{'}| \le 10^9\)。


分析:考虑化简一下边长的表达式:

  1. \(a_x,a_y \ge 0\),显然边长为 \(a_x+a_y=|a_x|+|a_y|\);
  2. \(a_x,a_y < 0\) 显然边长为 \(-a_x-a_y=|a_x|+|a_y|\);
  3. \(a_x \ge 0,a_y < 0\),这个可以感性理解下,\(a_x-a_y\) 可以看做在数轴上将 \(a_x\) 右移 \(|a_y|\) 单位长度,\(a_x+a_y\) 可以看做在数轴上将 \(a_x\) 向左平移 \(|a_y|\) 单位长度,由于 \(a_x \ge 0\),所以边长为后者,即 \(a_x-a_y=|a_x|+|a_y|\);
  4. \(a_x<0,a_y \ge 0\),根据绝对值的性质,边长可以写做 \(\max\{|a_y+a_x|,|a_y-a_x|\}\),与情况 \(3\) 同理,可得边长为 \(|a_y-a_x|\),即 \(a_y-a_x=|a_x|+|a_y|\);

综上,\(x,y\) 之间的边长为 \(|a_x|+|a_y|\)。

设 \(x,y\) 之间简单路径上经过的点为 \(u_1,u_2,...,u_k\),其中 \(u_1=x,u_k=y\),则长度为 \(|a_x|+|a_y|+2\sum_{2}^{k-1}|a_{u_i}|\),可以通过树链剖分修改和求解。

注意在查询前判断 \(\text{lca}(u,v)\) 是否等于 \(u\) 或 \(v\),这决定了 \(u_2\) 或 \(u_{k-1}\) 的值。

时间复杂度 \(O(n \log^2 n)\)。


1528C

题意:给定两棵树,求一个最大的集合 \(S\),满足对于任意 \(x,y \in S\),在第一棵树中 \(x,y\) 一个是另一个的祖先,第二棵树中 \(x,y\)都不是对方的祖先。


分析:考虑从第一个条件出发,要想满足第一个条件,所有点一定是在树上的某一条深度不断递增的链上,一次 dfs 可以求出所有的链。

现在的问题是怎么满足第二条链,一个很显然的方法是,当选择一个点时,将第二棵树中它的祖先和子树内所有点打上标记,这个可以用树链剖分,但是很麻烦。

考虑将祖先关系对应到 dfs 序上来,定义 \(L_i,R_i\) 为节点 \(i\) 在第二棵树 dfs 序上的最左边出现位置和最右边出现位置,dfs 第一棵树的过程中,是否选择当前节点 \(u\),取决于是否在已经选择的区间中,有无包含 \([L_u,R_u]\) 的区间或被 \(L_u,R_u\) 包含的区间,分如下三种情况:

  1. 没有上述区间,则选择 \(u\)。
  2. 有被 \([L_u,R_u]\) 包含的区间,此时不选择 \(u\),这样不会使得答案变大,且会造成更多的非法节点。
  3. 有包含 \([L_u,R_u]\) 的区间,删除包含它的区间并加入 \([L_u,R_u]\),虽然不会使答案变大,但是会减小非法节点的数量。

注意回溯的时候要撤销标记。

判断区间的包含关系可以用线段树解决,总复杂度 \(O(n \log n)\)。


1508C

题意:给定 \(n\) 个点的完全图,有 \(m\) 条边 \(<u_i,v_i,w_i>\) 确定了边权,另外的边没确定边权。如果给没确定边权的所有边赋予一个非负权值,满足所有边权值的异或和为 \(0\),求赋权后图中最小生成树的最小权值。\(1 \le n \le 2 \times 10^5,1 \le m \le \min\{2 \times 10^5,\frac{n(n-1)}{2}-1\},1 \le w_i \le 2^{30}-1\)。


分析:很显然,赋权时,只需要将一条边赋成给定权值的异或和,其余赋 \(0\),考虑到如果 \(n\) 很大,相对来说 \(m\) 很小了,此时大多数都是没有标权值的边,一定会存在一个没有标权值的边构成的环,那么将所有没标权值的边赋 \(0\),此时不会影响答案。

当存在 \(n\) 条没标权值的边就一定存在环,,即 \(m > \frac{n(n-1)}{2}-n\),由于 \(m_{max}=2 \times 10^5\),所以当 \(n\) 大于一个大约 \(O(\sqrt{2 \times 10^5})\) 的数就一定存在环,其余情况下可以直接枚举。

现在的问题转换为如何求一个大多数边权均为 \(0\) 的完全图最小生成树,可以用类似于 BFS 的方法处理只考虑边权为 \(0\) 的边的连通关系,用 set 维护一下还没有考虑到的点即可。其余边用 Kruskal 往上加就行。

顺带提一句可以省去小数据枚举的方法,在跑 Kruskal 的时候记录哪些边被选上,跑完后重置 dsu,按边权从小到大排序,找到第一个连接两个不同连通块的边,且在第一遍 Kruskal 时没被选上,这样就可以选上它替代掉一条 \(0\) 边。

标签:10,le,复杂度,CF,异或,做题,权值,DS,边权
来源: https://www.cnblogs.com/znstz2018/p/16367473.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有