【IOI 2018】Doll 机械娃娃
我感觉这个题作为Day2T1,有一定的挑战性。为$Rxd$没有完成这道题可惜。
我觉得这道题,如果按照前几个部分分的思路来想,就有可能绕进错误的思路中。因为比如说每个传感器最多只在序列中出现$2$次,很有可能会想到分别在每一个传感器之后用开关来控制。我在做这个题的时候就因为这个思路陷入僵局。事实上这个做法的弊端十分明显,首先如果可行的话,实现起来也会十分复杂,毕竟所有传感器序列中交错复杂,难于处理;其次,对于每一个传感器分别使用开关很可能导致开关的浪费。
这道题的两个关键的想法都源于其中的两个部分分,部分分的设置不仅是得分,往往对标算也有一定的启发作用。
把所有传感器的出口汇合在一起:
第$4$个$Subtask$中$n = 16$,这个$2$的幂次的数提示我们可以改变思路,把序列整体起来考虑可能更加简洁,更加清晰。
这么做会让题目简化,我们可以把那个汇集了所有传感器的开关向下建成一棵满二叉树(这里说明一下为什么每层都是满的,因为要保证每个开关都被经过了偶数次),底层$O(n)$个节点可以根据访问到的顺序确定它该连向那个传感器,或者连回开关的根。底层的节点数$L$应该是大于等于$\frac{n + 1}{2}$的最小的一个$2$的幂次。总的开关数就是$2L - 1$。在第$4$个$Subtask$中,我们按照这个方法只需要$15$个开关就能解决问题。
这里有一个小问题,就是如何知道某一个底层的出口会被第几次访问到。观察它的性质,发现它与$Fft$中的$rev$非常像,也就是从左到右第$i$个出口会被第$rev_{i}$次访问到。
于是看似这个算法很完美(事实上它已经十分优秀了,你可以光在后三个$Subtask$中得到$47$分),却有一点小瑕疵。当$n$是一个$2$的幂次多一点点的时候,$L$最坏会达到$n$个,也就是总节点数会被卡到$2n$个。这是一个很明显有很痛苦的瑕疵,所幸我们还有解决方法。
把冗余的开关剔除:
考虑到如果开关的某个出口没有被利用,我们之前的解决方法中,我们将它连向了开关的根,这是一次无用的滚动。我们唯一的问题就在于无用的滚动可能会过多。一个简单的想法就是如果某一个开关的两个出口都是连向开关的根的,那显然这个开关是无用的,我们可以把他直接去掉,把它父亲的出口连到开关的根去。如此做,直到没有什么可以删的点为止。注意,最后一次访问到的底层开关不能删除,因为要保证每一个开关都被经过了偶数次。
可惜直接这么做效果微乎其微,我们发现问题在于,如果直接把第$i$次访问到的底层的出口连向序列的第$i$个传感器,我们利用到的开关在底层中排布的是非常凌乱的,其实具体选那些出口没有什么太大关系,只要保证球滚出的顺序和要求的序列一样就可以了。我们可以只用$L$个底层出口中的后面$n$个,这么做就可以把所有利用到的开关分在一起,至于那些无用的开关就会被集中处理。这样节点的数量就会大大减少,总共有$logn$层开关,每层开关最多只有一个开关是不满的,所以不满的开关数最多$logn$个,由于满二叉树的节点数不会超过$n$个,故节点的数量就会在$n + logn$以内了。
$\bigodot$技巧&套路:
- 部分分对思路的禁锢和启发
- 线段树的思想,$Fft$的$rev$的意义
#include "doll.h"
#include <vector>
#include <algorithm> using namespace std; const int N = ; int n, L, tot = ;
int rev[N], bit[N], ps[N];
vector<int> a, c, x, y, to; int Solve(int l, int r) {
if (l == r) return (l >= L - n)? a[ps[l]] : N;
int md = (l + r) >> ;
int lc = Solve(l, md);
int rc = Solve(md + , r);
if (lc == N && rc == N) return N;
x.push_back(lc);
y.push_back(rc);
return -x.size();
} void create_circuit(int m, vector<int> a0) {
a = a0, n = a.size();
a.push_back();
for (L = ; L < n; L <<= );
for (int i = ; i < L; ++i)
rev[i] = (rev[i >> ] >> ) | (i & ? L >> : );
fill(bit, bit + L, -);
for (int i = L - n; i < L; ++i) bit[rev[i]] = i;
for (int i = ; i < L; ++i)
if (bit[i] != -) to.push_back(bit[i]);
for (int i = ; i < to.size(); ++i) ps[to[i]] = i + ;
int rt = Solve(, L - );
c.resize(m + , rt);
c[] = a[];
for (int &i : x) if (i == N) i = rt;
for (int &i : y) if (i == N) i = rt;
answer(c, x, y);
}
【IOI 2018】Doll 机械娃娃的更多相关文章
- 【IOI 2018】Werewolf 狼人
虽然作为IOI的Day1T3,但其实不是一道很难的题,或者说这道题其实比较套路吧. 接下来讲解一下这个题的做法: 如果你做过NOI 2018的Day1T1,并且看懂了题面,那你很快就会联想到这道题,因 ...
- [IOI2018]机械娃娃——线段树+构造
题目链接: IOI2018doll 题目大意:有一个起点和$m$个触发器,给出一个长度为$n$的序列$a$,要求从起点出发按$a$的顺序经过触发器并回到起点(一个触发器可能被经过多次也可能不被经过), ...
- 【IOI 2018】Combo 组合动作(模拟,小技巧)
题目链接 IOI的签到题感觉比NOI的签到题要简单啊,至少NOI同步赛我没有签到成功…… 其实这个题还是挺妙妙的,如果能够从题目出发,利用好限制,应该是可以想到的做法的. 接下来开始讲解具体的做法: ...
- 【IOI2018】机械娃娃
看到的时候感到很不可做,因为所有的开关都要状态归零.因此可以得到两分的好成绩. --然后 yhx-12243 说:这不是线段树优化建图吗? 于是我获得了启发,会做了-- 还不是和上次一样,通过提示做出 ...
- 【IOI 2018】Highway 高速公路收费
这是一道极好的图论题,虽然我一开始只会做$18$分,后来会做$51$分,看着题解想了好久才会做(吐槽官方题解:永远只有一句话),但这的确是一道好题,值得思考,也能启发思维. 如果要讲这道题,还是要从部 ...
- [IOI 2018] Werewolf
[题目链接] https://www.luogu.org/problemnew/show/P4899 [算法] 建出原图的最小/最大生成树的kruskal重构树然后二维数点 时间复杂度 ...
- Before NOIP 2018
目录 总结 刷题 2018 - 9 - 24 2018 - 9 - 25 2018 - 9 - 26 2018 - 9 - 27 2018 - 9 - 28 2018 - 9 - 29 2018 - ...
- WC2019 题目集
最近写的一些 WC2019 上讲的一些题.还是怕忘了,写点东西记录一下. LOJ2983 「WC2019」数树 题意 本题包含三个问题: 问题 0:已知两棵 \(n\) 个节点的树的形态(两棵树的节点 ...
- WC2019游记
本来不打算写游记的,但后来想了想这么一次难忘的经历总该留下点痕迹吧...... DAY-1 走之前的最后一天,因为前一天晚上打了CF,所以早上9点才到机房.写了一道圆方树深深地体会到了来自仙人掌的恶意 ...
随机推荐
- 4星|《钱的历史》:大英博物馆的钱币简史,彩图众多不适合在kindle上阅读
钱的历史(大英博物馆权威出品,一部金钱简史) 大英博物馆的两位钱币馆馆长的作品.非常专业.基本是世界钱币简史.从钱币的发展变迁讲到涉及到的历史大事,重心当然是欧洲的钱币史,中国.印度也各安排了一章. ...
- 32bit GM命令
GM 命令[32位服务端GM命令] //announce message this basicly tells a announcement on the whole server.. you can ...
- 字幕字体滚动插件——scroxt.js
README scroxt.js Overview scroxt.js是一个字体滚动的插件库,包括视频弹幕滚动,直播弹幕.直播弹幕强制模式.单行水平左右滚动.文本垂直滚动上下,用于简单快捷生成滚动字体 ...
- Daily Scrumming* 2015.10.29(Day 10)
一.总体情况总结 二.今明两天任务表 Member Today’s Task Tomorrow’s Task 江昊 了解微信API,与社团服务平台创业公司嗨社团创始人沟通,了解其平台运营方案与商业模式 ...
- 【区间DP】codevs3657 括号序列题解
题目描述 Description 我们用以下规则定义一个合法的括号序列: (1)空序列是合法的 (2)假如S是一个合法的序列,则 (S) 和[S]都是合法的 (3)假如A 和 B 都是合法的,那么AB ...
- Express搭建NodeJS项目
1.安装Node.js: 2.安装npm; 3.安装Express; 在本例中默认全局安装express 安装express生成器 如果没有安装express-generator或安装路径不对,会报以 ...
- Linux网卡配置文件路径是什么?要使服务器上外网,必须满足的条件有哪些?需要配置什么?
Linux网卡配置文件路径是什么?要使服务器上外网,必须满足的条件有哪些?需要配置什么? 答: 网卡配置文件路径:/etc/sysconfig/network-scripts/ifcfg- ...
- 个人作业week3案例分析
调研产品:博客园 第一部分 调研和评测 1.bug 1.不同种类浏览器的支持存在差异 bug描述:在不同浏览器下,部分博客内容显示的格式有明显不同 可尝试用下面两种不同的浏览器打开这个博客网址:htt ...
- 累计进度条 PSP 饼图
累计进度条 PSP 饼图 每周例行报告 本周PSP 类别 任务 开始时间 结束时间 被打断时间 总计工作时间 2016年9月24日 读书 构建之法-6.7章 19:00 20:00 2 58m ...
- cxgrid中,如何根据列名或字段名取得footer值
注意,不是根据index取得footer值cxgrdtbv1.DataController.Summary.FooterSummaryValues[0]; ------解决方案------------ ...