zoukankan      html  css  js  c++  java
  • NOI2020游记

    NOI2020 游记

    两位捧杯爷镇楼。

    背景

    省选day1T1爆零的情况下意外混进了省队(D类)。

    做了往年的题,感觉自己实力确实不太够。比如说,2018年的签到题(kruskal重构树)和2019年的签到题(斜率优化),凭我自己的能力都无法做出(“思维”和“算法的积累”两方面来讲,都是题目难度>我的水平)。

    2016和2017年的题,我倒是能做出一两道(比如2016的Day2T1“区间”和2017Day1T2的蚯蚓排队),但是也有签到题我做不出来(比如2016的Day1T1“优秀的拆分”我只会90分;2017的Day2T1“游戏”我只想到先(3^d)枚举再2-SAT,看了题解才知道可以优化为先(2^d)再2-SAT)。

    上述列举的这些都是当年的“签到题”,更不必说更难的题了,我只能打打暴力。

    事实上,按照往年的情况,如果做出了这些签到题,暴力不挂分的话,就能拿到银牌了。不过坏消息是签到题似乎一年比一年难了...


    Day-1(8.16),Day0(8.17),大家都在一起快乐狼人杀。然后都被李曙查水表了。


    试机的题是:NOI2019 Day1T2机器人,NOI2019 Day1T3 序列,NOI2019 Day2T3 I君的商店。

    试机后,大家聊天的句式都是:“哎,明天会不会要考xxx啊,如果考xxx我就没了啊...。我没了啊...”。其中“xxx”可以是任何一种我听都没听过的算法,可能已经远高于历年NOI的难度了,我不知道大家为什么都要这么说...。是为了搞别人心态吗?还是为了显示自己听过别人不知道的算法呢?

    哎,可能大家只是习惯性地假...


    晚上李曙给我嘱咐了几句:两天都会各有一道签到题,争取拿到70分。剩下的题每道题打30分暴力。每天130分,就能稳拿Ag了。

    正好我的目标也是拿到Ag。所以对这番分析深以为然。

    Day1

    (50+32+40=122)

    昨晚10点就睡了,半夜4:19醒了一次,又睡到6:40自然醒起床。可以说睡眠是很充足的,考试时精神也很好。上午考试前李曙给我们拍了个合照,本来我和djq站在一起,然后李曙一波安排,我就和dxm换了位置(你品,你细品 /滑稽)。


    本着先在签到题拿高分的想法,我先看T1。是个图论题,而且没什么想法(我好像经常对图论题毫无思路...,无论这题本身是什么难度...)。我想是不是以1为根,搜出dfs树,然后看有没有环?然后对环做背包?看上去很奇怪,于是先看T2。

    T2虽然题面很长,但看下来倒是觉得非常自然,也很好懂。看到前几个点(m)很小,一下就能想到做容斥。我粗略地以为时间复杂度是(O(2^mcdot ext{poly}(m))),然后以为自己能拿到40分。然后就继续去看T3了。此时时间大概是8:18。

    T3是个“很多维数点”...。看起来是个数据结构题。(O(nmlog n))是很简单的(考完后听别人一说才想到,做个二维前缀和就变成(O(nm))了。不过得分是一样的,所以也不重要,只是体现了我智商很低...)。部分分A((c_1=1,c_2=n)),我想了想,离线?树套树?分治?貌似都不对。好像可以莫队,不过是(O((n+m)sqrt{n}log {n}))的,不知道能不能过(10^5)...。没太多想,就先去写T2暴力了。


    先写了个(O(2^n))暴力。因为后面不管些什么都可以用它拍。写完这个9:06。然后继续写“(O(2^mcdot ext{poly}(m)))暴力”。发现自己一开始想错了,这个暴力并不是(O(2^mcdot ext{poly}(m)))而是(O(2^mcdot n))。可能只能拿20分,这就要低于李曙给我定的计划了。于是又进一步想想,发现可以用树链剖分优化到(O(2^mmlog^2n)),期望拿到32分。虽然比之前以为的40分低了一些,但还是达到了李曙说的30分。

    T2似乎后面还能再搞一个树形DP:(dp[i][j])表示第(i)个点向上的前(j)条边里必须至少有一个重要边。我不太清楚它是(O(n^2))还是(O(n^3))的,不过应该还能再拿到一些分。但是看分不多我又不是很确定,就先没写这个。决定稳妥一点,先写T1,T3暴力,最后再写这个DP。此时9:52(毕竟写树链剖分还是要花不少时间的)。


    再看T1,首先发现我原来那个“找出所有环然后做背包”的思路彻底假了,因为环的数量可以是指数级的。不过很快惊喜地发现可以直接在图上做DP:设(dp[i][j])表示第(i)天到达节点(j),能获得的最大收益。转移直接枚举出边即可。时间复杂度(O(T(n+m)))。可以得到40分。然后又发现下面两点:图是一个环的部分分很简单,于是写了。

    现在是10:44,T1总共有50分。感觉不错,先去上了个厕所。此时想到,(T)这么大,应该是矩阵快速幂。不过10秒钟后,我把自己否决了。我在草稿纸上写下:矩阵快速幂(x):max不能矩乘。考完试才知道是我naive了。哎,完美地记录了我的无知...


    虽然T1没拿到预期的70分,不过我看没有除快速幂外的其他思路,就没有继续纠结,转而去写T3部分分。(O(nmlog n))的部分分就是用树状数组维护,非常好写。部分分A,我思考以后发现分治、树套树,这些似乎都不靠谱,于是尝试去写sqrt log的莫队。写完以后一测大样例,没过!我又对拍了小数据,才发现是我树状数组写错了。简而言之就是,改变了不该改变的参数,偷懒没有使用替身变量导致的错误(都是平时习惯不好,如果函数都写const int& 就没这个问题了)。又自己造了一组(10^5,2 imes10^5)的随机数据,实测3.2s左右,感觉能过(下午查分发现只跑了1.8s)。

    搞完这些,已经12:15了。这时候我发现一个大问题,T1的对拍的时候,因为一些不熟悉linux系统而导致的错误,我的程序其实没拍上...。修正了这个错误后,我重新对拍了T1,T2。T2过拍了。T1却没有过。(一开始搞错了,以为两个都没有过。反正那2分钟还挺刺激的)。好在发现T1是个小错误,改了就好了。

    12:40左右试图开始写T2的树形DP部分分。但是时间不够了,没写完。最后就检查了一下文件啥的,提交提交,就结束了。


    嗯。整个过程大概就是这样了。虽然分比同学低不少,但是没有挂分。又想到我的同学都是集训队水平,所以我感觉,也还行?然后李曙又笑嘻嘻地说不错不错(虽然他和谁都这么说),所以我还挺开心的。

    Day2

    (0+20+5=25)

    昨天听说比银牌线略差一点。那今天要加把劲了。我计划不惜一切代价猛干T1,其实这个计划无比正确,只可惜我没有坚持执行。后面我们会分析到原因。

    先来看看比赛过程。开场看T1。理解了题意后,最开始以为是网络流,但是立即就发现不对。

    于是尝试某种贪心。一种想法是,可以将所有原料排好序,然后最大的和最小的匹配。其实这就是(m=n-1)时的正解,并且可以修改后得到本题正解。但我只是凭空猜出来这个贪心,而没有注意到(m)(n)的关系。所以我手玩一下小样例,发现最后一个点过不去,就放弃了这种做法(于是就远离正解了...)。

    后来又猜了一种贪心,尝试枚举一个断点,断点左边的第一个和右边的第一个配,第二个和第二个配,以此类推...。不过这个好像也不太对。我写了一半放弃了。这里有一点心得,感觉不太对的算法基本写着写着都会假掉。因为如果是正解,你一定可以想好每一个细节,或者说,它的每一个细节都是“经得起检视的”。如果你自己对这个算法都“支支吾吾”,无法实现出细节,那它肯定就不对了。

    此时大概一个小时过去了。因为T2题面太长,T3看起来又像是我不擅长的图论题,于是决定继续看T1:写T1的暴力。最朴素的想法是,枚举(m)道菜里每道菜用了哪两种原料(或者第二种不用)。那么枚举量是(n^mcdot (n+1)^m),似乎只能过最小的(n,mleq 4)的点。并且,枚举完之后还无法计算出每种原料具体给每道菜分配多少,可能还需要高斯消元?我没细想,但这个作为最低档的部分分也太离谱了,于是就没写。

    然后我又想了一个暴力,它基于的猜想是,所有可行的方案,都可以被描述为(n)种原料的一个排列,按这个排列排好后,依次把原料倒入每一道菜就能得到这个方案。朴素枚举所有排列的话,复杂度是(O(n!cdot (n+m)))的,看起来可以通过(n,mleq 10)的分,并且看起来很有优化前途:既然是排列,那么我们可以随机交换两项,看是否变优,也就是用模拟退火算法来做。

    于是我立刻动手写了这个枚举全排列的暴力。可惜它过不了第二个样例...。我仔细想了一下,它确实是不对的,只要有一种(d_i)很大的原料,这种构造方式就不一定能得到最优方案了。于是,刚刚想到的所有优化前途都泡汤了...


    此时已经10:00左右,我决定放弃T1,去看看T2, T3。

    T2题面虽然长,但还是好懂的。

    本题显然是需要结论的,否则怎么面对“无穷”这个概念呢?计算机的算力再强,如果只用朴素的枚举,也无法对抗无穷啊!

    然而我就是一直没想到什么靠谱的结论。可能是我的分析能力还不太够;也可以说我对本题,只是看懂了定义,却对这个定义没有一个感性的理解,导致想了很久,还是徘徊在原点...

    好在根据数据范围,判样例可以拿到12分,这可比T1的暴力分好拿多了。我基于这个样例,瞎写了一些东西。我猜测,一组树可行,当且仅当存在某一层,满足:任意一个“这层所有节点的子集”,都能对应为,某棵树在这一层上的所有叶子节点。

    然后这个结论,我也不知道是太强了还是太弱了,既不知道充分性也不知道必要性。反正我只知道它能过小样例(1~4)但是过不了其他样例。但既然能过样例1~3,那得分肯定不会低于12分,于是就交了这个。事实上它得了20分。


    写完T2这一通东西,时间还剩最后一个小时了。我赶紧去看T3。我以前完全不知道弦图这个概念,也不知道任何性质。后来知道,A部分分是直接输出最短路,但这个可能也不太好猜?反正我在考场上完全没想到。

    我看到部分分B是以一条链为主干,我以为可以做一个,类似于在序列上DP的东西。写了一下,发现假了,完全不对。

    最后时间不够了,只能全删掉,改成输出-1。得到了5分。


    于是这场比赛就遗憾的结束了。最后T1的那个全排列假做法也没来得及改,交上去得了0分。我全场就晕头晕脑地写了个T2假结论,还有T3输出-1骗了5分。

    总结分析

    结局:银牌线(274)。我(247) Cu了。

    Day1,主要还是打得太保守了。可能是什么都要拍,就导致进展非常慢。但是我确实拍出来一个小错误(T1),并且最后我也没挂分,打满了我自己认为的暴力,所以说明对拍还是很重要的。

    那么我的分析是,是否可以尽可能先想到更高的分,再动手开始写。这样写完正解,还是写个小暴力来拍,就比我现在的情况要好。我现在是先写个40分暴力,再写个10分暴力和它拍,然后如果再要写正解,那可能一共就要写3个程序了,有点来不及。

    下次应该尝试一下,先硬想一个小时,想出正解(或者较高部分分)的思路,这样就可以省去“40分暴力”的这个环节。

    当然,这与我水平的提高,也就是能不能想到,也是有很大关系的。


    我们事后来看Day2,其实大家分都很低。主要的区分度就在T1,能不能做出来或者拿到较高的分。

    这个题的特点是,没留什么纯暴力分,没法爆搜或者枚举。逼着你想结论,哪怕只是一个部分的结论(比如(m=n-1)的那个)。当然,如果你只是纯靠猜(和我一样),那你一定会因为样例而怀疑自己的结论。所以说到底还是要靠分析。

    如果从事后的角度分析,我就算Day2爆零也能拿Cu,结果并不会变差。而如果专注干T1,则有机会想出正解,拿到银牌。所以我的策略可以说,傻了。当然,这里面既有运气的成分,也有不会判断题目难度而导致的考场决策力不行。


    综合这两天来看,主要的问题都是:中等题做不出来。这里“中等题”,指的就是Day1T1,Day2T1,这种NOI比赛里的“签到题”。但客观地讲,即使是NOI最简单的题,也是有一定难度的,所以我称之为中等题。

    回家以后要多练这种,有一定难度,有思维要求,并且综合了多种算法的OI题。它们可能在平时nfls六校联考的模拟赛中,可能在LOJ里的各种真题中,可能在CF的div1 D,E,F里...。要勇于把它们啃下来,才能进一步提高实力。

  • 相关阅读:
    css3 动画+动画库
    垃圾回收 及 内存泄漏
    做菜体会
    微信小程序
    微信公众号2
    JavaScript 原生事件
    Bootstrap框架
    Less 和 Sass
    HTML标签总结
    表单元素
  • 原文地址:https://www.cnblogs.com/dysyn1314/p/13525855.html
Copyright © 2011-2022 走看看