杭州集训 Day 1
杭州集训 Day 1
课前
早上很早很早就起了,大概 5:40 吧,然后就感觉肚子疼。因为昨天晚上吃的喷射战士。在厕所足足待到 6:00 才出来。然后听了一会崩铁的演唱会回放,一直没来得及看,听了几首大概 6:30 收拾东西准备吃饭了。
30 元一顿的早饭,必须好好看看,结果啥也没有,素包子,“正宗烧麦”是不是就是米饭陷儿的?》》》不懂,吃的不爽。明天早上叫外卖。
到机房发现那小破电脑难用的,不好评价。本来也没打算上课写代码,估计老师讲课要十几分钟速通一个题就算是自己电脑也够呛。
今天是 hs_black 讲课,讲一些简单算法和数据结构,但是 hs_black 迟到了,差评,(不如两年前帅了)能感觉到 hs_black 深深的无力感,报课前明明要求学生 NOIP 范围内所有算法掌握,结果 hs_black 还得给他们现场教学 Trie 和树上背包啥的。
笔记
P5691
由于答案一定是整数,所以可以直接枚举所有的解。直接枚举所有的解复杂度是 \(O(m^n)\),所以直接把次数分成两截,分别预处理出前 \(n/2\) 的结果后半截的结果,然后两个数组去凑加起来等于 \(0\)。复杂度 \(O(m^{n/2})\)
P8817
1 -> B 和 C -> 1 是相对独立的,如果不考虑重复的情况,直接仿照折半搜索的方式解就行。考虑重复,以 B -> C 为中间断开点。然后维护 A,C,D 的次大和第三大值,这样就保证不重复
CF1373F
很有意思的思维题,很难想到是二分。
由于 zzz 说了这个题算法是二分,考虑如何二分。发现貌似并没有单调的数组。唯一单调的是网络基站的位置。但是并不好维护,所以打开脑洞,二分 \(b_1\) 分给 \(a_1\) 的值。然后贪心求解即可。
但是想到了一个 \(O(n^2)\) 的差分约束,后来发现题解区有个佬将这个算法优化到了 \(O(n)\)。然后就可做了。
P4064
二分答案二分 \(\min\{a_i\}\)。后来想了个逆推用线段树和优先队列维护的想法,然后 zzz 说这样逆推复杂度会假如果出题人数据构造的好直接就会被卡。但是大体想法是对的。二分答案肯定没问题,至于后边的操作可以贪心的想区间,若要使当前点 \(i\) 达到 \(mid\),一定加区间叠至 \(mid\),其中对后面影响最大的方案一定是 \(r\) 最靠右的合法 \((l≤i)\) 区间。之后用过的 \(r<i\) 删去,新的 \(l≤i\) 且未加入堆的加进来。之后修改区间可以差分也可以线段树树状数组什么的维护一下就可以了。
P1080
经典老题了。微扰交换俩个数,设下标为 \(i,j\) ,列出不等式假设最优的情况,化简有贪心结论,按照 \(a \times b\) 的方式排序最优。因为要乘法发现爆 \(long\) \(long\),写个高精度。
P3619
当 \(b_i > 0\) 时,直接按照 \(t_i\) 排序显然是最优的。如果是负数的情况,对于 \(i,j\) 两个位置,分别列出合法式子,化简后有
由于第一个式子更松,所以范围更大,所以再列出不等式消掉 \(T\) 那么有 \(t_i + b_i<t_j+b_j\),按照这个方式排序就可以了。
AGC023F
考虑到如果一个节点权值为 \(0\),那么能选这个点立刻就选上即可,所以我们将其和其父亲合并,意思是选完它父亲立刻选择它自己。
假设没有树的限制,考虑下面的问题:给定 \(n\) 个 \(01\) 串,要求安排他们之间的顺序,使得逆序对个数最小怎么做。
用微扰法,考虑相邻两个 \(01\) 串 \(a, b\),并尝试交换他们的顺序。
- \(a\) 在 \(b\) 前面,\(cnt(a,1) \times cnt(b,0)\)
- \(b\) 在 \(a\) 前面,\(cnt(b,1) \times cnt(a,0)\)
化简有 \(\frac{cnt(a,1)}{cnt(a,0)} < \frac{cnt(b,1)}{cnt(b,0)}\)
回到树上的问题,拥有最小 \(\frac{cnt(a,1)}{cnt(a,0)}\) 放到越靠前越好,因此一旦其父亲被释放,立刻选择这个子节点,所以我们贪心的将其和父亲节点进行合并即可。
P4643
表面博弈论,其实是个非常简单的贪心。由于双方都是使用的最优策略,所以他一定会拿那个可以使他得分最多的那个点,所以考虑如何把边权一起转移到点权上。所以,将点权大小翻成原来的两倍,然后将边权加到点上,最后答案除以二即可。
东兴保卫战
东兴保卫战 牛客挑战赛49 https://ac.nowcoder.com/acm/contest/11189/E
引理:对于一个森林,点数 - 边数 = 联通块的个数
然后把点设为 \(1\) 的权值,把边设为 \(-1\) 的权值。然后就和阿狸和桃子的游戏一样了。
P2512
省流:负载平衡问题网络流
设向左传递 \(x_i\),有 \(a_i - x_i+x_{i+1}=avg\)
\(x_{i+1}=avg-a_i+x_i=i \times avg - \sum a_i + x_1 = C_i + x_1\)
原问题转化为最小化 \(\sum |C_i+x_1|\) 的值,取中位数时最小
P2587
全集房的人被一个田忌赛马团灭
所有贪心方案全被 zzz hack 掉
菜就多练
后来发现我们绕进了一个思维误区,我们一直在想我们全员实力被对方碾压的情况而忽视了我方存在等位对位我方比对手强的情况。如果最弱能赢最弱的,直接赢。如果最强能赢最强,直接赢。否则田忌赛马,最弱打最强。但不要无脑直接写,要注意条件优先级。
CF1442D
对于不降的性质,对于这些数组,只有一个取前缀,剩下的要么不取要么取满,这样才能保证最优。因为不降的话越往后取越大,如果每个都只取一截显然是亏的。对于这个性质,我们将每一个数组中的所有数加起来,数组中的数字个数为体积,加起来的和为重量,在之后特殊处理取前缀的那个数组就可以了。
具体的,于每个数组 \(i\),我们都求出 \(f[i][t]\) 表示除了 \(i\) 以外的数组做 01 背包,选择 $t $ 个元素的最大价值是多少。那么答案就是 \(max_imax_t(f[i][t]+sum[i][k-t])\)
设 \(f[l,r][t]\) 表示除了 \(l,r\) 的 01 背包,有 \(f[l,mid]=f[l,r]+f[mid+1,r],f[mid+1,r]=f[l,r]+f[l,mid]\),\(+\) 表示加入区间内的物品,复杂度 \(O(nk \log n)\)
P3295
统计答案可以对应点连边,然后用并查集维护连通块,答案就是 \(9 \times 10^{连通块个数-1}\)。然而边数太多考虑优化,我们用 ST 表优化连边,\(f[i][j]\) 表示从 \(i\) 开始长度为 \(2^j\) 的区间,那么每次询问可以用 ST 表拆成两对区间对应相等。最后统计时从上向下 push,比如 \(f[i][j]\)
和 \(f[k][j]\) 有边,那么 \(f[i][j-1]\)
和 \(f[k][j-1]\)
有边,\(f[i+2^{j-1}][j-1]\) 和 \(f[j+2^{j-1}][j-1]\) 有边
CF413E
将迷宫看成长度为 \(n\) 的线段,用线段树维护,对于区间 \(L, R\) 来说,维护四个标记表示从$ L$ 的上面/下面,走到 \(R\) 的上面/下面最短路是多少,这个信息也是可以合并的
P1502
对于每个点,它的贡献是一个矩阵,那么相当于询问二维平面上的被覆盖权值最大的点。做扫描线,并且用线段树维护最大值即可。
P3498
暴力枚举 \(k\),那么总共串的个数为 \(O(n \log n)\) 级别的,每个子串用两个哈希值表示(正串的哈希值,反串的哈希值,无顺序)。用 \(set\) 把哈希值插入,最后查询 \(set\) 的大小即可。
P3065
第一种情况显然是前缀,显然如果存在一个串是我当前串的前缀,肯定是不合法的。
考虑一个字符串什么时候最小,在 Trie 树上每次都走的最左边。
可以得到当前字母是所有出边中最小的,当前字母和其他字母连有向边表示字典关系,最后拓扑排序即可。而且,如果拓扑排序成功,那么拓扑序就是新的大小关系。
P5854
\(O(n \log n)\) 建造方法,用 ST 表每次找到区间的最小值,递归建树。
\(O(n)\) 建造方法,维护一个从根节点一直走右儿子的极右链,插入一个新点 \(x\),找到最后一个比 \(x\) 小的位置,设其为 \(y\),我们让 \(y\) 的右儿子变成 \(x\),把原来 \(y\) 的右儿子变成 \(x\) 的左儿子
SP3734
没调出来,笛卡尔树配上计数类 dp 着实抽象,弃了,很难想象这是个蓝题。
大体思路就是按照高度最小值分治,设 \(f[x][k]\) 表示当前区间放了 \(k\) 个点的方案数,那么类似树形背包,处理合并的两边可以用组合数。
CF992E
如果满足 \(a_i=s_i - 1\),那么 \(s_i=2s_{i+1}\),前缀和翻倍,所以最多翻倍 \(\log n\) 次。
用线段树维护 \(a_i-s_{i-1}\),可以发现最多有 \(\log n\) 个位置 \(≥0\),所以暴力搜索这些位置,维护区间最大值即可。
下课
上课的时候 hs_black 讲的题基本一半我都回答了,但是我回答的又有一半是假的,好尴尬呜呜。但是很多人在场跟听天书一样,除了第一排部分人以外基本都在挂机,听 hanss6 说他们那里很多人上课直接启动了。
晚上回去打 ABC 更是坐牢。由于知道只能打一会有事儿得出去所以选择随便写俩题然后口胡一下后几个题就走。A,B 非常水,C 直接全排列枚举出来然后 check 就好,全排列极限是 \(11\), 刚好满足数据范围 submission
F 题也是抽象,写了一个暴力过了 submission 逻辑就是模仿 Hankson 的趣味题那个题的预处理暴力作法,搜两边,把一个数和把它反转后的数拼成一对,如果 \(n\) 刚好是 \(x\) 和它翻转数乘积的正整数倍数,就记录 \(x\) 然后继续搜索,直到出现合法解。由于这种能拆成回文数乘积的形式并不多,所以直接枚举复杂度并不是很高,提前预处理出一些数字降低复杂度然后凑就可以了。
至于 G 题,只能说能 TM 想到在 ABC 里出 3300 的题纯属逆天,纪念传奇 ABC G 题 3300 干掉 tourist。G 题没看题解,抛开数据范围不谈跑 \(n\) 轮反悔贪心可做,然后应该是可以数据结构维护,不知道。3300 的题加上是又臭又长的数据结构也懒得学了。整套题里唯一比较好玩的就是 D 题,但是是原,考虑预处理一些数逼近。对于 \(n\) 是偶数的情况,\(n\) 位的回文数的个数实际上就是 \(n/2\) 位的自然数的个数,奇数同理。预处理算出第 \(k\) 大的回文数一共有几位,按照左半部分递增逼近就行了。submission。E 题朴素 bfs 就可以,submission