IOI2020 集训队作业 Part 1

1. CF627E Orchestra

题意:给定 \(r\times c\) 的矩阵中的 \(n\) 个点,问有多少个子矩形包含 \(\ge k\) 个点。\(r,c,n\le 3\times 10^3,k\le 10\)
情况:看了题解“链表”和“\(k\) 很小”提示后,自己想出。
调试:(1)链表头和尾(m+1)虽然是空的,但也要有pre和nxt(2)二分左右端点细节
收获:固定上边界后观察下边界往下移动一格对所有点对应右指针位置状态造成的动态影响,并从中发现可以暴力的性质。
题解:朴素做法是枚举上下边界,再横向利用双指针统计。考虑上边界固定时,下边界往下一格对每个左边界的右边界整体造成的影响。更具体地,由于下边界的插入相当于插入了若干个点,考虑一个下边界上的点的影响。很明显,如果维护每个有值的左边界 \(l\) 的右指针 \(r_l\),则其贡献为 \((l-pre_l)(m-r_l+1)\),其中 \(pre_l\) 为上一个(目前)有值的纵坐标(用链表维护,\(nxt_l\) 同理)。一个下边界的点 \(u\) 只会对 \(nxt_u\)\(pre_u\) 以及 \(l\ge u-k\)\(r_l\) 修改,其中 \(r_l\) 的修改就是 \(r_l\gets pre_{r_l}\),总个数不超过 \(11\) 个,可以暴力。复杂度 \(O(rc+rnk)\)
代码:submission

2. CF639E Bear and Paradox

之前做过

3. CF639F Bear and Chemistry

之前做过

4. CF666D Chain Reaction

题意:有 \(4\) 个机器人分别位于 \((x_i,y_i)\),你需要为每个机器人指定一个去向 \((x'_i,y'_i)\),需满足 \(x_i=x'i\)\(y_i=y'_i\)。构造一种方案,使得 \(\max_{i=1}^{4} (|x_i-x'_i|+|y_i-y'_i|)\) 最小。数据组数 \(\le 50\),坐标范围 \(\in [-10^8,10^8]\)
情况:自己做出,觉得很水。
调试:几乎没有。
收获:几乎没有。
题解:
先 dfs 每个机器人在哪一条直线上(如上图红色标号),再 dfs 每个机器人去编号为几的顶点,这样 \(4\) 条边的解析式中就有至少 \(2\) 条已经已经确定。分类讨论:如果 \(4\) 条确定,直接判断并更新;如果 \(3\) 条确定,第 \(4\) 条显然已知;如果 \(2\) 条确定,则这两条必定平行,且此时正方形边长已知,设待定的两条直线中的一条的坐标为 \(x\),将答案表示成 \(\max(|x-a_1|,|x-a_2|,|x-a_3|,|x-a_4|)\) 的形式(不妨设 \(a_1\le a_2\le a_3\le a_4\)),取 \(x=\frac{a_1+a_4}{2}\) 最优。
代码:submission

5. CF666E Forensic Examination

题意:给定模式串 \(S\)\(m\) 个文本串 \(T_i\)\(q\) 次询问 \(S[pl,pr]\)\(T_l,T_{l+1},...,T_r\) 中的哪一个文本串中出现次数最多,以及最大出现次数是多少(多个编号输出编号最小的)。\(|S|,q\le 5\times 10^5,\sum |T_i|\le 5\times 10^4\)
情况:看题解。
调试:(1)SAM 板子(2)依次插入 \(T_i\) 时未把 \(las:=1\)(3)\(S\) 的前缀对应的 SAM 节点在插入 \(T_i\) 后因为 clone 的存在而可能改变
收获:对刚学的 SAM 进行了巩固;SAM 中一个节点在 parent-tree 上的子树为所有以这个串作为后缀的串;SAM-build 中的 cur 是每个前缀对应的节点,parent-tree 上一个节点子树内有多少个 cur 就是这个串的 \(|endpos|\),在只有一个大串时递推,多个大串时线段树合并;快速定位一个子串对应的 SAM 节点可使用从该子串右端点对应前缀所对应节点开始倍增跳 parent 的方法,判断跳到的点的 \(len\ge r-l+1\) 与否即可。
题解:SAM 的每个节点上维护一棵线段树,插入 \(T_{i,j}\) 时在 \(cur\) 的线段树上把 \(i\) 位置令成 \(1\),将询问离线到每个 \(S[pl,pr]\) 对应的节点上,在 parent-tree 上做线段树合并的同时统计每个节点上的询问的答案。
代码:submission

6. CF671D Roads in Yusland

题意:给定树上 \(m\) 条路径 \((x_i,y_i)\)(保证 \(y\)\(x\) 的祖先),每条路径有一个权值 \(c_i\),要求用最少的权值和覆盖所有 \(n-1\) 条边。\(n,m\le 3\times 10^5\)
情况:DP 自己想出,用线段树合并优化 DP 受了题解提示。
调试:非常久。(1)pushdown 没有判左右儿子为空的情况(2)l 打成 1 并始终没有发现(3)一些修改本可单点却写了区间、一些没必要的修改导致 RE/MLE(3)线段树合并第一个儿子时应该直接 rt[x]=rt[y](4)带 tag 的线段树合并 merge(x,y,l,r) 时应有 pushdown(x),pushdown(y);\(x,y\) 都要 pushdown
收获:巩固了一种 DP 状态设计套路;了解到树上二维 DP 在难以用常规方法优化时可以使用线段树合并;了解了在线段树合并时打 tag 的注意事项
题解:设 \(f(u,i)\) 表示 \(u\) 子树内所有边都覆盖完,向上延伸到了深度 \(i\) 的最小价值。\(f(u,i)=\min_{v\in son(u)}\min(f(v,i)+f(u,i\le k\le dep_u),f(u,i)+f(v,j\le k\le dep_u))\)\(f(u=x_i,y_i)\gets f(u,dep_{y_i}\le j\le dep_u)+c_i\)。首先把 \(\le dep_u\) 的限制去掉,通过在 \(u\) 处把线段树上 \(dep_u+1\) 处变成 \(+\infty\) 做到(注意只需要单点改就行了,因为下面的点也做了一样的事情)。对于第二个转移式,$dep_{y_i}\le $ 的限制其实是多余的,因为如果比它还小,肯定在那个更小的延伸点出记录了不劣的信息,所以这部分变成全局查最小值。线段树合并时,每个节点维护区间最小值,这样就可以在从根下来的过程中记录当前所有右侧的最小值;到叶子处合并时,直接用 curminx,curminy 分别加给 t[y].mn,t[x].mn,然后 t[x].mn=min(t[x].mn,t[y].mn);在 x,y 中其中一个为空处合并时(不妨设 xy 非空),对 y 打上 tag+=curminx,后续 pushdown 时注意如果一个子节点为空就忽略这个子节点(不要新开一个点),以及 pushdown(x),pushdown(y)
代码:submission

7. CF671E Organizing a Race

题意:一条路由 \(1,2,...,n\) 这些加油站组成,\(i\)\(i+1\) 之间有长度为 \(w_i\) 的道路,在加油站 \(i\) 能加能跑 \(g_i\) 长度的油。请选出 \(r-l+1\) 最大的 \([l,r]\),使得一辆油箱无限大的汽车能从 \(l\to r\),也能从 \(r\to l\)(行程前都会把油箱清空);在选择之前,你可以进行 \(k\) 次操作,每次选一个 \(g_i\le g_i+1\)\(n\le 10^5,k\le 10^9\)
情况:看了很久题解,然后发现没有想象的难。
调试:几乎没有。
收获:(1)练习了线段树二分(2)学会了不怕先把需要满足的限制条件写成带 \(\forall,\exists\) 的形式,再结合实际情况,用移项、换元法等推式子,最终转化成 \min,\max 或其他更加简洁的形式(3)学到了对于两个或多个条件的最优化问题,先考虑满足其中一个条件的策略,再在这个策略的规则下寻找一个满足第二个条件的最优解
题解:能从 \(l\to r\) 等价于 \(\forall i\in [l,r),\sum_{j=l}^{i}w_j\le \sum_{j=l}^{i}g_j\);能从 \(r\to l\) 等价于 \(\forall i\in [l,r),\sum_{j=i}^{r-1}w_j\le \sum_{j=i+1}^{r}g_j\)。将求和式写作前缀和形式,得 \(\forall i\in [l,r],W_i-W_{l-1}\le G_i-G_{l-1},W_{r-1}-W_{i-1}\le G_r-G_i\);移项,令 \(c_i=W_{i-1}-G_{i-1},d_i=G_i-W_{i-1}\) 得,\(\forall i\in [l,r),c_{i+1}\le c_l,d_{i}\le d_r\),即 \(c_l=\max_{i=l}^r c_i,d_r=\max_{i=l}^r d_i\)。对一个位置的 \(g_i\gets g_i+1\) 造成的影响是让所有 \(c_{j>i}-1,d_{j\ge i}+1\)。从 \(n\)\(1\) 枚举 \(l\)。将两个限制分开考虑。对于 \(c\) 的限制,必须逐个击破 \(>l\) 的第一个 \(c_{x}\ge c_l\) 的位置 \(x_1\)(使之降低为 \(c_l\),同时它后面的所有 \(c\) 都跟着减),\(>x_1\) 的第一个 \(c_{x}>c_{x_1}\) 的位置 \(x_2\)……可以用单调栈维护栈 \(x\)。由于减的次数不能超过 \(k\),满足 \(c\) 的限制的最远候选 \(r'\) 为最大的 \(r'=x_{p+1}-1\) 使得 \(c_{x_p}-c_l\le k\),二分得到。现在我们的游戏规则变成了将 \(g_{x_1-1},g_{x_2-1},...,g_{x_t-1}(x_t\le r,x_{t+1}>r)\) 分别减 \(1\),求仍能满足 \(d'_r+k'=\max_{i=l}^r d'_i(1)\) 的最远的 \(r\)\(k'\) 为操作完 \(1\sim t\) 后还剩下的次数,全用来操作 \(g_r\) 肯定最优)。事实上我们可以在到达一个 \(l\) 时直接得到此时的 \(d'\),而不用真的每次去操作 \(g\),具体方法是在单调栈加入和弹出时实时维护 \(d'\) 的后缀加和后缀减和区间 \(\max\)。考虑线段树上二分,想知道右儿子的区间里有没有合法的 \(r\),结合 \(d'_r+k'=d_r+k\),就是要判断 \(d_r+k=\max_{i=l}^{r}d'_i\),容易发现 \(r\) 取区间内的最大值一定是最优的,而 \(d_{\max_{\text{rightson}}}+k\ge \max_{i=mid+1}^{r}d'_i\),因此只需判断 \(d_{\max_{\text{rightson}}}+k\ge \max_{i=l}^{mid}d'_i\),不等式右侧直接在从根往下走的过程中用左子树信息附带记录即可,左侧相当于静态数组 \(d\) 区间查最值,用 ST 表提前记录即可。这样就找到了最大的 \(r\)。复杂度 \(O(n\log n)\)
代码:submission

9. CF643F Bears and Juice

通信题,比较神秘。

10.CF643G Choosing Ads

题意:给定一个长度为 \(n(n\le 1.5\times 10^5)\) 的序列和一个整数 \(20\le p\le 100\),有 \(m\) 个操作,操作要么是区间赋值,要么是询问区间内出现次数最多的 \(\lfloor{100\over p}\rfloor\) 个数(也可以不全部输出,但必须输出出现次数占 \(\ge p\%\) 的数)。
情况:通过看题解学习线段树维护摩尔投票的经典套路。
调试:无
收获:学会了用线段树维护摩尔投票。
题解:线段树每个节点维护一个大小 \(\le \lfloor{100\over p}\rfloor\)vector<pair<int,int> > 表示摩尔投票的最终结果(人+票数)。摩尔投票是这样一个过程,对于当前序列,如果不同人的个数大于 \(\lfloor{100\over p}\rfloor\),则任选 \(\lfloor{100\over p}\rfloor+1\) 个人各删一票,没票踢出。pushup 时模拟投票即可,转移为常数。特别地,当 \(p=50\) 时,问题就是绝对众数,即每次删除两个不同的数,最后剩下至多一种数;这就是 NOI2022D1T1 的做法。
代码:submission

AGC020E Encoding Subsets

题意:一个 01 串可以通过这样的方式压缩:每次选择其一个连续出现 \(k\ge 2\) 次的子串 \(P\),然后将它写作 (Pxk)。无需完全压缩。定义一个 01 串 \(T\) 为 01 串 \(S\) 的子集当且仅当 \(\forall i,T_i\le S_i\)。求 \(S\) 的所有子集的合法压缩方案数之和。\(|S|\le 300\)
情况:区间 DP 部分子集想出,子集部分的循环节统计部分受题解提示。
调试:无
收获:以串本身为状态的记忆化搜索甚至可以跑得很快;涉及子集的问题思路断了时可考虑位运算的结果的含义。
题解:一个确定 01 串的压缩方案数的求法是简单的,设 \(f(l,r)\) 表示 \([l,r]\) 的答案,\(g(l,r)\) 表示 \([l,r]\) 最外层为单个 \((Pxk)\) 时的方案数。\(f(l,r)\)\(g(l,k)\cdot f(k+1,r)\) 处转移;\(g(l,r)\) 枚举循环节长度 \(len\mid (r-l+1)\)\(f(l,l+len-1)\)转移。考虑原问题,\(f(l,r)\) 的转移不变,\(g(l,r)\) 转移有一定技巧,还是枚举循环节长度,这次需要知道有多少个 \([l,r]\) 的子集能写成以 \(len\) 循环的形式,那其实就是从 \(S[l,l+len-1]\operatorname{and}S[l+len,l+2len-1]\operatorname{and}...\operatorname{and}S[r-len+1,r]\)\(f(l,l+len-1)\) 转移,所以我们的记忆化搜索应该是 int dp(int n,bitset<N>s)(返回的是 \(f(1,n)\))。
代码:submission

AGC020F Arcs on a Circle

之前做过
收获:(1)在实数域内的期望位置关系问题,通常满足:题目中的关系只与各元素所在位置的整数部分,以及小数部分的相对大小有关;因此全排列各元素小数部分的相对大小,将每个 1 单位长度作出 n 等分点,从而把取数变成取点,可以进一步解决。(2)线段覆盖 DP 的一种典型状态设计:设 \(f(s,i,j)\) 表示已经用了 \(s\) 这些线段,起点在前 \(i\) 个点之中,最远已经完整覆盖到第 \(j\) 个点,的概率。
题解:本题的特殊性:在环上。解决方法:断环为链。断环为链有讲究,如果我们任选一条线段的起点定为断点,则可能出现下图的情况,就还需要考虑那种从尾部又穿到头部来补救的情形。

但是如果以最长的线段的起点作为起头,那么处于尾部的线段即使穿到首部也不会伸到比第一条线段的结尾更长的地方,因此可以忽略。
代码:submission

AGC021E Ball Eat Chameleons

题意:有多少个长为 \(k\)'R'/'B'\(s\),使得存在一种将第 \(i\) 个球喂给 \(n\) 只变色龙中的一只的方案,满足所有操作过后所有变色龙都变成红色。初始时所有变色龙都是蓝色;蓝色变色龙变红当且仅当体内红球比蓝球多,红色变色龙变蓝当且仅当体内蓝球比红球多。\(k,n\le 5\times 10^5\)
情况:看题解
调试:几乎没有
收获:熟悉了“不能触碰某条线”的更简单做法(旋转坐标系,从而不用斜着走,而是被触碰的线变成了斜线);一个括号串包含至少 \(k\) 组独立(即一个字符只能用一次)的 () 子序列当且仅当它的每个前缀的前缀和 \(\ge -(c_{\texttt{)}}-k)\);了解了固定贪心策略以解决不规则的去重问题:一个方案合法的条件是用这种方式得到的结果合法;分类讨论以缩小视野。
题解:当 \(R\ge B+N\) 时一定合法;当 \(R<B\) 时一定不合法;当 \(B<R<B+N\) 时构造一种最优的策略,以判断一个 RB 串是否合法:让 \(N-(R-B)\) 只变色龙依次吃 R、B,剩下的 \(R-B\) 只每只恰好多吃一个红球。因此一个 RB 串合法的条件为能够选出有序的 RB 至少 \(N-(R-B)\) 组(不能重复选一个位置)。这进一步等价于将 R 看成 +1,B 看成 -1 得到的序列的每个前缀和都 \(\ge -(B-(N-(R-B)))=N-R\)。证明略(很好证)。因此就变成了从 \((0,0)\) 每步可以向右(R)或向上(B)走,不能走到 \(y=R-N\) 或它的上方的方案数:\({R+B\choose R}-{R+B\choose 2R-n+1}\)。但是 \(R=B\) 时会出一点小问题(感性理解一下),不过它的 \(s_k\) 一定 \(=\texttt B\)(否则不可能合法),因此变成了 \(R'=R,B'=B-1\) 的情况。
代码:submission

AGC022E Median Replace

题意:一个长度为奇数的 01 串是好的当且仅当可以通过一系列“选择连续三个数并替换成其中位数”的操作将其变成 1。有一个含 ?01 串,求有多少种设置 ? 的方案使得所得串是好的。\(n\le 10^6\)
情况:看题解
调试:几乎没有
收获:了解了“字符合并”类问题的一种思路:贪心考虑合并的优先级,然后用栈等方式模拟这个过程;学到了 101/001/110 等 01 串可以删去其中的一个 10/01,原串的中位数完全取决于剩下的一个数。
题解:对于一个确定的 01 串,要想尽可能让它最后成为 1,策略一定是先把 000 都选出来合并了,再每次选一个 01/10 删除(顺序不影响),最后考察 1 的个数是否 \(\ge\) 0 的个数。因此对于一个前缀 \(i\),我们只需要考虑 \(i+1,i+2\) 有没有可能贡献更加优先的,所以需要预留 0。一个巧妙的实现方法是用栈模拟,维护一个自顶至底依次为一段连续的 0 和一段连续的 1 的栈。若当前加入 1:栈顶为 0,则弹出栈顶;栈顶为 1 且 1 的个数 \(\le 1\),则入栈。若当前加入 0:栈顶为 1,则加入 0;栈顶为 0,若有 2 个 0 则替换成 1 个 0(000→0),否则加入 0。设 \(f(i,0/1/2,0/1/2)\) DP 即可,最后取 \(\sum_{a\le b} f(n,a,b)\) 即可。
代码:submission

AGC024D Isomorphism Freak

题意:对于一棵无根树,如果以 \(u,v\) 为根同构,则将 \(u,v\) 染成同一种颜色,否则染成不同颜色。在树上添加任意多个点,使树的颜色数达到最小可能值,输出颜色数最小值以及最后树的叶子数最小值。\(n\le 100\)
情况:看题解
调试:无
收获:(1)一些构造思想(2)一棵每层节点度数相同的以某个点或边为根的树,以同一层内的点为根树是同构的
题解:考虑答案的下界,很明显是直径的一半。同时可以发现最终的树一定是中心对称的,可以用反证法。因此不难构造出一组方案:以直径中点(边)为根,每层点的儿子数都变成这一层现有点儿子数的最大值(并在下一层添加若干点)。通过测样例发现,并不一定能满足叶子数最小的限制,因此需要暴力枚举所有点或边作为根更新答案。
代码:submission

AGC028C Min Cost Cycle

题意:一个包含 \(n(n-1)\) 条有向边的有向完全图中,每个点都有 \(a_i,b_i\) 两个权值。一条边 \(u\to v\) 的权值为 \(\min(a_u,b_v)\);一条哈密顿路的权值为依次经过的 \(n\) 条边的权值和。求哈密顿路权值最小值。
情况:看题解
调试:无
收获:若权值计算方法特殊,可以考察计算权值的要素的性质。最优化或计数难以入手时,不妨先从判定性角度考虑,然后结合贪心等手段与最优化联系起来。
题解:边权由点权计算,自然考虑对于一条哈密顿路,每个点的 \(a,b\) 被选择的情况。最优化难以入手,考虑如何判定一个从 \(\{a_1,b_1,a_2,b_2,...,a_3,b_3\}\) 中选 \(n\) 个的方案是否合法(即可以构造一条哈密顿路恰好满足这个条件)。Lemma:合法当且仅当存在 \(i\) 使得 \(a_i,b_i\)都被选,或所选元素全是 \(a\) 或全是 \(b\)。贪心地选集合中的最小的 \(n\) 个元素,若不合法,则贪心地将第 \(n\) 小换成第 \(n+1\) 小,若仍不合法,则有两种换法:将 \(n+1\) 换成 \(n+2\)\(n\) 换成 \(n+1\),都必然合法。
代码:submission

posted @ 2023-02-23 19:20  pengyule  阅读(37)  评论(0编辑  收藏  举报