HNOI 2014
D1T1:画框 frame
题意:给你两个n阶正整数方阵,请你求最大的\( \sum_{i = 1}^{n} A_{i, p_i}\times \sum_{i = 1}^{n} B_{i, p_i} \)其中\({p_i}\)是一个n的排列。\(n \le 70\)。
如果A=B,这就是一个二分图最大完美匹配问题,那么我们可以用费用流或者KM算法解决,然而A却可以不等于B,我们需要另辟蹊径。
当年我看到这道题就只会随机化乱搞,现在看来,如果仔细的思考还是可以搞出来的。
想到,我们可以求出对于A来说的最小值,附带一个对于B的值(即\(\sum_{i = 1}^{n}A_{i, p_i}\)和\(\sum_{i = 1}^{n}B_{i, p_i}\)),和对于B来说的最小值,附带对于A的值。不妨将以上的值抽象成二维平面上的点p(x,y)和q(x,y)。那么答案一定是基于对上述做法调整,因为我要适当增大p(x,y)中的某一个值,而减小另外一个值,使得x*y更小,这另我们想到了双曲线,我们要求的点一定位于过p(x,y)的双曲线之下,那么由于双曲线是下凸的,就是求一段下凸壳上点。求下凸壳。由于没法使用卷凸包法或者水平序法(这样会导致能通过遍历所有点(\(n!\)个点。。)求出下凸壳上所有点从而进行了多余计算,而我么只要求一个xy坐标相乘值最小的点),考虑分治。
分治法求下凸壳上的xy乘积最小的点。连结上述求出的两个点p,q,要求的点一定是p或者q或者在d连线的左下方,而从连线向左下推进最远的点t也一定位于凸壳上,那么答案就是t或者分别以p,t向下做的凸壳上的点或者t,q向下做的凸壳上,于是便可进行递归分治下去,复杂度为求O(最小完美匹配)*O(log在下凸壳上的点数),下凸壳上的点数是log(n!)级别的(不要问我怎么知道的)。至于如何求t点,将过p,q的直线方程写出来,就是:\((y_q-y_p)x+(x_p-x_q)y+c=0\)c是一个常数,那么我们要最小化ax+by,只要把g[i][j]设成A[i][j]*a+B[i][j]*b就行了。
D1T2:世界树 worldtree
题意:给你一棵树和q个操作,每次要你求m[i]个节点h[1],h[2],…,h[m[i]]所管辖的点数。定义某个点被h[p]管辖当距离这个点最近的唯一点是h[p]或者h[p]的标号最小。n≤300000, q≤300000, m[1]+m[2]+…+m[q] ≤300000。
当年考试前考过一道相似的题,没去改,考试时还是不会;现在还是不会。望后人警惕,考过的题一定要改,特别是出题人在身边的,不懂的一定要天台见(讨论题目啊我当然是这个意思)。
没事想想暴力:每次枚举所有点,找到离自己最近的点。复杂度n*n*q。
我们是否做了重复计算?对于一些点,我们并不要再一次枚举的,比如有那么一条链,或者有那么一颗子树,没有被选中的点,那么每次只要给最近的那个点加size就行了。
引入虚树的概念:一颗树的虚树指包含了所有给定点,并收缩度数为二的点的最少边数的联通子图。
以下转自hzc:
对于每个询问,建出这些点的一棵虚树。所谓虚树就是用最少的边使得这些点连通,并将度数为2的点都给缩起来。
一个性质是,由个点建出的虚树中的节点数为O(k)。
虚树的建法也很简单,把点按照DFS序排序,那么相邻两点(首尾视作相邻)的LCA以及原本的点就构成了虚树。
我们求出虚树上到每个点的最近点。由于有上面那个性质,我们可以暴力BFS求。
现在的问题就是被我们缩掉的那些点,以及这些点之外的若干子树。
如果被缩起来的一条边两端的最近点相同,那么整条边上被缩起来所有点的最近点就是两端的最近点。
否则一定存在一个位置,以其为界,两边的最近点分别是两个端点的最近点。
这个只需要知道两个端点的距离以及两端到最近点的距离,用树上倍增就能求出来。
而一棵虚树外的子树的最近点就是其在虚树上的根的最近点。
那么这个问题就解决了。复杂度大概是(n+k)log(n)。
D1T3:米特运输 meat
题意:求修改尽量少的节点的值,使得所有每个节点的孩子节点的值相同且和为该节点的值。
当年被卡题意了,看到描述长度读都没读题。。sign。。sign。。后人警惕啊!描述越复杂,题目越简单,因为出题人只能用语文来提高难度了。
注意到如果确定某个节点的值,那么整颗树都确定下来的,那么我们可以枚举确定那些点,\(O(n^2)\)。50分到手。暴力code。
AC做法也很好想的。用根节点的取值代替整颗树的状态,那么对于每个节点不变求出根节点的取值,取众数便是答案。是\(O(n^2)\)的。这等价于,从上往下推,让根节点随意取个值,然后推出每个节点的值与根节点的倍数关系,是\(O(n)\)的。注意单纯这样搞可能要用到高精度,取对数即可。
D2T1:抄卡组 hs
题意: 给定N个字符串,包含小写英文字母、数字、和可以匹配任意长度个的字符(包含0个)通配符"*",问所有字符串是否两两匹配。
做法:两个Judge:Jud_with_tp() 当所有串都有通配符时只需要所有串的不带通配符的前缀和后缀相同即说明所有串都相同。 Jud_with_kmp() 当有串不含通配符时,取最短的那一个S,其他的串就相当于被通配符划分成了多个不含通配符的子串,此时就只要按顺序往后,所有子串都能在S中一一匹配到,则说明这两个串是相同的。可使用kmp,不过觉得暴力匹配也能过,没试了。
复杂度:Jud_with_tp() O(nLen) Jud_with_kmp() O(nLen) 都是线性的。
写的很丑,谨慎观看。
D2T2:道路堵塞 road
题意:给个有向图,问依次去掉最短路上的边后的最短路的长度。
考场上写了暴力,然后发现边比较少,于是加了个求桥边的判-1,目测写错了。
如果是无向图,从1到n,从n到1,两次dijkstra。从最短路上某条边E1开始,到达某条边起点;反方向从E2进行到达这条边的终点。那么若最短路上从E1到E2之间的边被截断,就可以从E1到这条边再到E2,跳过断路的这一部分,相当于求并联在去掉边两端的路径。用线段树维护最小值即可。
以上做法能过。。。但题目要求的是有向图。。对于二元环来说显然不可操啊。。。于是vfk看不下去了,出了组数据把我(和很多人)卡了。。目前只能暴力spfa+堆优化。最开始删掉给定的边,在spfa的时候不要清空dist数组,从1到n每次加上去一条边再跑spfa,由于加一条边可能只会更新一小部分点,所以复杂度会较底,把跑出来的到给定路径上的点的dist加上从那个点走最短路到n的距离放到一个堆里去,每次取最小的即可。
这是一道坑爹题,没代码233333。
D2T3:江南乐 game
题意:给你N堆棋子,轮流把不少于f个子的堆分成至少两堆,请问先手是否必胜。
我是傻到什么地步了。。竟然把0个子也算一堆,导致从考场到前一天一直以为题目有问题。我也不会SG函数嘎,下面是转的http://blog.csdn.net/gromah/article/details/27326991
对于10分的数据:明显当石子数大于1时,先手胜。因为只有一堆,先手只要把石子全拆成只有1个的若干堆就赢了,但如果本来就只有1个石子,就是后手赢,复杂度O(1)。
对于70分的数据:直接暴力求在当前的 f 值下每个石堆对的的sg值即可。每堆石子有O(n)中分裂方式,每个分裂方式的sg求值是O(1)的,有O(n)个石子,复杂度O(n ^ 2)。
对于100分的数据:我们考虑两个性质
1、(n / i)(商向下取整),至多有 2 * sqrt(n) 个不同的结果。
2、如果 n / i == n / (i + 2) ,那么通过将石子分裂成 i 份得到的 i 堆石子的sg值异或和与将石子分裂成 i + 2 份石子所得到的结果相同。
如果上述两个性质是对的,我们就可以只枚举 n / i 来求解,因为有很多分裂方式在本质上是相同的,我们完全可以不考虑。
现在我们来证明这些性质:
证明性质1:在1 - sqrt(n) 之间,因为只有 sqrt(n) 个数,所以 (n / i) 在1 - sqrt(n) 之间当然最多只有sqrt(n) 个结果。
在 sqrt(n) - n 之间,因为 n / n = 1 , n / sqrt(n) = sqrt(n),n 除以该范围内的数的结果必然在1 - sqrt(n) 之间 。所以 (n / i) 在 sqrt(n) - n 之间也只会出现sqrt(n) 个不同的结果。
综上,在1 - n之间,(n / i) 至多有 2 * sqrt(n) 个不同的结果,性质 1 是正确的。
证明性质2:因为把 n 个石子按照题目要求分成 i 份,会产生 n % i 个石子数为 n / i + 1 的石头堆,i - n % i 个石子数为 n / i 的石头堆。(这个挺显然的)
而把 n 个石子按照题目要求分成 i + 1 份,就相当于在分成了 i 份的基础上,从 n / i 个石子数为 n / i + 1 的石头堆中,各拿出1个石子,组成一个新的石子数为n / i 的石头堆。
而把 n 个石子按题目要求分成 i + 2 份的话,就相当于做了两次组新石子堆的工作,其石子堆的奇偶性不变,因为你操作了两次,所以各种石子堆的改变量就必然是2的倍数,既然这样,石子堆的sg值异或和就不会变。
所以性质 2 是正确的。
好的,现在我们保证了这个算法的正确性,来说说具体做法吧。
对于每个石子数n,我们枚举它的 n / i 值,然后取分裂成 n / i 份和 n / (i +1) 份的两种情况就可以了。
实现过程中,我们还可以进行记忆化搜索来提高程序的效率。
每个石子数的sg求值是 O(sqrt(n)) 的,有 O(n) 个石子,所以时间复杂度是 O(n * sqrt(n)) 的。
搞懂之后顿觉sb,还麻烦了bakser大爷。
首先暴力如下code
只要记住一句话即可:游戏和的SG函数等于各子游戏SG函数的NIM和(就是异或和),而mex是针对其后继状态来计算SG函数值。
上面给出的参考博客中的代码(包括翱犇的代码)先计算了一次SG函数值,再跑mex。我感觉可以直接跑mex啊,在跑的过程中算SG不就行了。。然后纠结好久,最后发现,人家开的全局数组来算mex啊!!果断在函数内定义计算mex的数组,然后A了。。速度还快些。。对比暴力code只加了一行,然后就是30分的差距,可见省选之残酷性。。
正解code
HNOI 2014的更多相关文章
- HNOI 2014 米特运输(图论)
HNOI 2014 米特运输 题目大意 给一棵树,每个点有自己的权值,要求更改一些点的权值,使得整棵树满足两个条件: 同一个父亲的所有子节点权值相同 父节点的取值为所有子节点的和 答案输出最少要更改的 ...
- 图论(KM算法,脑洞题):HNOI 2014 画框(frame)
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABPoAAANFCAIAAABtIwXVAAAgAElEQVR4nOydeVxTV/r/n9ertaJEC4
- 数据结构(虚树,动态规划):HNOI 2014 世界树
Hnoi2014 世界树 Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平 ...
- [HNOI 2014]画框
Description 题库链接 \(T\) 组询问,每组询问给你个 \(2\times N\) 的带权二分图,两个权值 \(a,b\) ,让你做匹配使得 \[\sum a\times \sum b\ ...
- [HNOI 2014]江南乐
Description 题库链接 给你指定一个数 \(f\) ,并给你 \(T\) 组游戏,每组有 \(n\) 堆石子, \(A,B\) 两人轮流对石子进行操作,每次你可以选择其中任意一堆数量不小于 ...
- [HNOI 2014]世界树
Description 题库链接 给出一棵 \(n\) 个节点的树, \(q\) 次询问,每次给出 \(k\) 个关键点.树上所有的点会被最靠近的关键点管辖,若距离相等则选编号最小的那个.求每个关键点 ...
- [HNOI 2014]道路堵塞
Description A国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国 交通部指定了一条从城市1到城市N的路径,并且保证这条路径的长度是所有 ...
- [HNOI 2014]米特运输
Description 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储 存一直是一个大问题.D星上有N个城市,我们将其顺序编号为1到N,1号城市 ...
- 解题:HNOI 2014 世界树
题面 首先建虚树 DFS求虚树上每个点所属的点和到它所属点的距离,然后在=考虑虚树所有的边(对应原树一条链).如果两个端点所属节点不同就倍增出分界点统计答案,否则不用管(之后会统计到的):注意根节点特 ...
随机推荐
- python基础----列表生成式、生成器表达式
结论: 1.把列表解析的[]换成()得到的就是生成器表达式 2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存 3.Python不但使用迭代器协议,让for循环变得更加通用 ...
- angular2 获取到的数据无法实时更新的问题
在修改完组件数据之后调用下面两句: this.changeDetectorRef.markForCheck(); this.changeDetectorRef.detectChanges(); 注入到 ...
- java面试之闭包(closure)
今天在学习Openresty的时候回顾了下闭包这个问题,感觉很久没有深入的了解这块的内容的,只是之前js的时候学习过闭包,突然一问,感觉不记得闭包了: 看了一个比较有趣的答案: 闭包,顾名思义,就是把 ...
- 9.Android UiAutomator正则表达式的使用
一.正则表达式元字符: 1.一些常用元字符: 元字符 描述 . 表示任意一个字符 \s 空格字符(空格键.tab.换行.换页.回车) \S 非空字符串([^\s]) \d 一个数字(相当于[0-9]中 ...
- Lucene 索引与检索架构图
- codeforces 876 C. Classroom Watch
http://codeforces.com/contest/876/problem/C C. Classroom Watch time limit per test 1 second memory l ...
- 第七周 ch04 课下测试补交
2017-2018-1 20155335 <信息安全系统设计基础>第7周 课下测试博客 本人不慎忘记去交dao'zhi 测试题目: SEQ+对SEQ的改变有() A . PC的计算挪到取指 ...
- 数组C - 玛雅日历
During his last sabbatical, professor M. A. Ya made a surprising discovery about the old Maya calend ...
- python初步学习-异常
异常 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在python无法正常处理程序时就会发生一个异常. 异常是python对象,表示一个错误. 当python脚本 ...
- Python面向对象学习 1 (什么是面向对象,面向对象的应用场景,待更新)
程序设计的三种基本结构: 面向对象,面向过程,函数式编程 1,什么是面向对象编程 面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就 ...