BalticOI 2020 做题记录
D1T1 「BalticOI 2020」色彩
不难想到二分,但是如果你的mid一直加你就爆出n了
于是我们考虑向左向右来回跳,只要找到一个合适的起点即可
这个起点可以考虑设答案是n倒推出来,这样你最后问的一定是1或n
然后你就得到了起点,先输入这个起点然后直接二分,每次还是左右来回跳
容易发现这样的询问一定合法
时间复杂度\(O(Tlogn)\)
D1T3 「BalticOI 2020」小丑
考虑只有一次询问怎么做,我们直接把每一条边依次加进去,用并查集就可以维护奇环了
多组询问考虑莫队,但是并查集不能动态删除一条边怎么办呢?
考虑回滚莫队,还是左端点在同一块的一起处理,按右端点排序,莫队的左端点初始在块头,右端点在\(m\)
每次我们先加右端点比当前少的边,再加左端点少的边,处理询问以后批量回退
时间复杂度\(O(n\sqrt{n}logn)\),有梦想,正常写法就能过
D2T1 「BalticOI 2020」图
我们把每一个连通块分开处理
考虑设一个点是\(x\)
那么找一棵生成树我们就可以用\(x\)表示其他所有所有点的权值
通过生成树上的非树边我们可以列出一些方程
如果可以解出多个\(x\)就输出NO,如果只解出一个那么这个连通块就确定了
如果没有解出来那么就需要考虑极值问题
根据初中知识我们发现多个一次绝对值函数和的最小值就是在所有零点的中位数处取到
于是就可以轻松确定了
时间复杂度\(O(nlogn)\)(如果你像我一样不会nth_element的话)
D2T2 「BalticOI 2020」村庄
先考虑最小值怎么构造
考虑从下往上构造,不难发现一个点的子树内的点要尽量在这棵子树内匹配完
于是考虑这样一个做法
对于x的子树我们让这棵子树最多只有他一个点没有匹配点,其他都匹配了
我们考虑对于x的没有匹配的儿子
如果这样的儿子至少有一个,那么把他们和x构成一个环,环上依次匹配,刚好完备,答案加上2*cnt,cnt是这样的叶子的个数
如果没有,那么x就暂时不匹配,留到父亲那里去匹配
最后如果根节点没有被匹配,那么就随便找他的一个儿子(这个儿子显然已经匹配),然后把这个点加入到这个儿子所在的大环中,答案+2即可
再考虑最大值怎么构造
ztc和wangdy巨佬教我做的,他们tql
我们考虑答案的上界就是所有点的min(n-size[x],size[x])*2
我们考虑怎么取到这个上界
考虑提出这棵树的一个中心
然后把中心分出去的几棵子树两两配对,保证配对的点一定不在同一棵子树中
容易发现由于重心关于子树大小的性质,这样所有点都取到上述的极值,而且由于这一性质,这样一定有解
构造只需要按顺序拿出从中心开始dfs的dfs序,dfs序为i的点和dfs序为i+n/2的点配对即可
时间复杂度\(O(n)\)
D2T3 「BalticOI 2020」病毒
ztc 教我做的题,他tql
我们不难发现这题是AC自动机上dp
按照常规套路我们建出AC自动机扣掉不合法的点得到一个阉割版
然后就开始dp
设\(f[i][j][k]\)表示第\(i\)个突变表能从AC自动机上的\(j\)号点走到\(k\)号点,扩展后的最短总长度
我们发现这样不好转移
于是我们把每个突变表的所有后缀拿出来,再和所有单个的基因并在一起得到\(G+\sum k\)个串
接下来我们改一下dp的定义
设\(f[i][j][k]\)表示第\(i\)个字符串能从AC自动机上的\(j\)号点走到\(k\)号点,扩展后的最短总长度
我们发现这个dp就很好转移了
对于一个长度大于\(1\)的后缀,它只能由比它短一个的后缀在前面加一个数字转移过来
对于一个大于\(1\)的数字,他只能由突变表上它代表的那些完整的后缀转移过来
对于一个长度等于\(1\)的后缀,它只能由它对应的数字转移过来
于是我们写一个记忆化搜索就好了
发现这个dp有环怎么办呢?
我们发现这是一个类似于最短路的过程
用dijkstra的思想,用一个堆来增广每一个状态
即把上面转移的顺序反过来
这样就结束了吗?
我们发现还有一个小细节
对于一个后缀添加一个数字\(x\)转移到一个新的后缀的情况
我们如果增广到这个后缀的时候数字\(x\)还没被更新,那么就转移不了
但是如果以后数字\(x\)的值被算出来了,当前这个转移依然可以进行
所以上面那个转移需要双向转移,在后缀处和数字处分别转移一次
时间复杂度是\(O(Nl^3log{Nl^3})\)