Copper Loser 的题解……

Day1 T1 方格染色

有一个 \(n\times m\) 的网格,有 \(Q\) 次操作,每次形如有三种:将 \((x_i+j,y_i)\)/\((x_i,y_i+j)\)/\((x_i+j,y_i+j)\) 染色,其中 \(j=0,1\dots L_i-1\)。 第三种操作至多只有 \(5\) 次,问之中有多少个格子被染过色。

扫描线板子题,首先令 \(ans=\sum\limits_{i=1}^QL_i\),然后考虑如何去掉被重复染色的部分。

对于横线与竖线的,离散化之后使用扫描线求值即可。

由于斜线之后 \(O(1)\) 条,可以将每条斜线和所有其他线的交点算出来,然后去重即可。

时间复杂度 \(O(Q\log n)\)。

Day1 T2 桂花树

给定一棵有 \(n\) 个节点的树 \(T\),保证一个节点的父亲编号小于它的编号。问有多少个有 \(n+m\) 的节点的树 \(T'\),满足对于所有 \(1\le i<j\le n\) \(i,j\) 在 \(T\) 和 \(T'\) 上的最近公共祖先相同,对于所有 \(1\le i<j\le n+m\),\(i\) 和 \(j\) 在 \(T'\) 中的最近公共祖先编号 \(\le \max(i,j)+k\)。

对于第一条限制,就确定了 \(T'\) 上 \(1,2\dots n\) 形成的虚树就是 \(T\)。

我们考虑从 \(T'\) 中逐个删除节点得到 \(T\) 的过程。

考虑特殊情况 \(k=0\),则对于当前最大的节点 \(u\),不存在 \(1\le i,j<u\),\(i,j\) 的最近公共祖先为 \(u\)。这也就意味着 \(u\) 至多只有一棵子树,所以可以直接将这个点删去。

反转这个过程,也就意味这我们可以从小到大把节点插在一条树边上,或者挂在一个节点下面,成为它的儿子。假设当前大小为 \(siz\),则一共有 \(2\times siz-1\) 种方案,所以这种情况的答案就是 \(\prod\limits_{i=1}^m(2n+2i-3)\),可以直接 \(O(m)\) 计算。

这给了我们一个想法,对于当前要插入的节点其他的节点会是完全相同的,这也就意味着答案可能和 \(T\) 的形态无关,实际上确实是这样的。

考虑回到一般情况 \(k=10\),仍然考虑从大到小删除,考虑当前最大的节点 \(u\),由于限制被放宽了,所以它可能会存在若干个儿子。但是,由于公共祖先编号要 \(\le \max(i,j)+k\),也就意味着它至多只有一个儿子的子树中存在编号 \(<u-k\) 的节点。那么,我们先跳过这个节点的删除,接着删除比它小的节点,由于上面的那一条限制,在删除到某一个编号 \(v \ge u-k\) 的节点时,\(u\) 只剩下一个儿子了,也就可以把 \(u\) 删除了。所以我们考虑在删除 \(v\) 的过程中同时删除掉 \(u\)。

不难发现 \(u\) 都会对应唯一的 \(v\),\(v\) 也至多只能对应一个 \(u\)。

考虑反过来加入的过程,加入一个节点 \(u\) 时,可能会将一个 \(\le u+k\) 的节点作为父亲捆绑加入,而这种情况下,这一对点只能是放在一条树边上的。

设计 DP 状态 \(f_{i,S}\) 表示当前要加入 \(n+i\) 号节点,在 \(n+i\sim n+i+k-1\) 中已经被加入了的节点集合为 \(S\)。则最终的答案就是 \(f_{m+1,\varnothing}\)。

考虑转移:

如果 \(n+i\in S\),说明 \(n+i\) 号节点已经被加入了,所以直接跳过,\(f_{i+1,S\setminus \{i\}}\gets f_{i,S}\)。

否则,我们可以按照正常的方式转移 \(n+i\),也就是 \(f_{i+1,S}\gets f_{i,S}\times [2\times (n+i-1+|S|)-1]\)。

或者可以捆绑一个 \(v\in ([n+i+1,n+i+k]\cap \mathbb{N})\setminus S\) 的节点一起加入,转移为 \(f_{i+1,S\cup {v}}\gets f_{i,S}\times (n+i-1+|S|-1)\)。

时间复杂度 \(O(mk2^k)\)。

Day1 T3 深搜

一棵生成树 \(T\),以及一个非树边边集 \(E\),给定若干个关键点,问有多少个 \(E\) 的子集 \(E'\),使得存在关键点 \(u\),使得在 \(T\) 中加入 \(E'\) 中的所有边得到的图,\(T\) 可以是一个以 \(u\) 为根的 dfs 树。

是 dfs 树,也就意味着 \(E'\) 中所有的边都是返祖边,不是横插边。

一个边集 \(E'\) 可能对于多个关键点合法,考虑容斥。

设对于关键点集合 \(S\),在以这个集合中任意一个点为根是,均是返祖边的边数量为 \(cnt(S)\),则最终答案为 \(\sum\limits{S}(-1)^{|S|+1}2^{cnt(S)}\)。

考虑什么样的边会对点集 \(S\) 来说均是返祖边:

建出 \(S\) 点集在 \(T\) 上的虚树,则 \(E'\) 要么是虚树的一条树边,要么被虚树的一条虚边包含,要么就是一条不在虚树上的返祖边(在以某一个虚树或虚边上的点的子树内)。

钦定 \(1\) 为根,考虑在 \(S\) 所有点的 lca 处计算贡献,记 \(f_u\) 表示当前以 \(u\) 为根,只考虑子树内的边的所有情况的带符号和。记 \(d_u\) 为在 \(u\) 的子树外的返祖边数量(可能在以 \(1\) 为根时是横插边,但是以 \(u\) 为根是返祖边)。

则 \(u\) 最终对答案的贡献为 \(-f_u\times 2^{d_u}\)。

考虑如何转移,假设 \(v\) 为 \(u\) 的子树,\(f_v\) 向 \(f_u\) 的转移会带上很多从满足条件的边的贡献,具体的,就是满足上面说的两种情况的贡献,所以考虑事实维护一个数组 \(g_u\) 来处理这个贡献。不难知道 \(g_u\) 初始为 \(f_u\)。

如果有一条边 \((u,v_0)\),则 \(v_0\) 的子树内所有的 \(g_u\) 变成 \(2\times g_u\);将 \(u\) 向 \(fa_u\) 转移时,对于 \(u\) 某一个子树 \(v\) 内的所有返祖边 \(c_v\),会将所有不在 \(v\) 子树内的点 \(g_u\) 变成 \(2^{c_v}\times g_u\)。

发现这些变化都是子树乘,可以通过对点的 dfs 序建线段树维护。

由于 \(u\) 只能从每一个子树内选择一个点转移,所以可以使用背包维护 \(dp_{0/1/2/3}\)。

最终的 \(f_u\),如果 \(u\) 是关键点,则 \(f_u=-dp_0-dp_1-dp_2-dp_3+dp_2+dp_3=-dp_0-dp_1\)。

如果 \(u\) 不是关键点,则 \(f_u=dp_2+dp_3\)。

但是发现这样处理只能通过特殊性质 AB,也就意味着,有横插边对答案造成了影响。

我们发现,被漏算的部分,是 \(dp_2\) 的转移时,假设选择的子树为 \(v_1\) 和 \(v_2\),同时没有选择点 \(u\),这时横跨了 \(v_1,v_2\) 的横插边是会对答案做贡献的,具体如下图中的红边:

还是将子树拍成 dfs,则这样的每条边 \(u_0,u_1\),都会对 \(v1\in[l_1,r_1],v2\in [l_2,r_2]\) 或 \(v2\in[l_1,r_1],v1\in [l_2,r_2]\) 的答案做贡献。

将每一对 \((v_1,v_2)\) 抽象成二维平面上的一个点,我们相当于要做若干次矩形乘和一次矩形和的操作。

对于每一个 \(u\),把这样的操作离散化之后做一次扫描线即可。

总体复杂度 \(O((n+m)\log n)\)。

Day2 T1 贸易

给定一个带边权内向完全二叉树,同时给出若干条从祖先到子孙的边,定义 \(dis(x,y)\) 为 \(x\) 到 \(y\) 的最短路长度,求 \(\sum\limits_{x}\sum\limits_{y}dis(x,y)\)。

考虑处理出所有的 \(f_{x,y}\),表示从祖先 \(x\) 走到子孙 \(y\) 的最短路,\(a_{y,x}\) 为从子孙 \(y\) 走到祖先 \(x\) 的距离,则最终 \(dis(u,v)\) 就等于 \(g_{u,lca}+f_{lca,v}\),其中 \(lca\) 为 \(u,v\) 的最近公共祖先。

\(f_{x,y}\) 的值可以使用一个类似 floyd 的过程求出,\(g_{x,y}\) 可以直接通过树上差分得到。

最终求和是简单的。

总体复杂度 \(O(n^22^n)\)。

Day2 T2 字符串

给定一个字符串 \(S\),多次询问 \(i,r\),有多少个 \(1\le l\le i\),使得 \(S[i,i+l-1]<S^T[i+l,i+2l-1]\)。

由于 \(S[i,i+l-1]<S^T[i+l,i+2l-1]\),即 \(S[i,i+l-1]+S[i+l,i+2l-1]<S^T[i+l,i+2l-1]+S^T[i+l-1,i]\),即 \(S[i,i+2*l-1]<S^T[i,i+2l-1]\)。

对于 \(S'=SS^T\),上式等价于 \(S'[i,i+2l-1]<S'[2*n-(i+2l-1)+1,2*n-i+1]\)。

将 \(S'\) 后缀排序,上式在大多数情况下等价于 \(rk_i<rk_{2*n-(i+2l-1)+1}\),从大往小扫 \(sa\) 数组,则对于每一个 \(i\),我们可以使用树状数组维护出做贡献的 \(l\)。

现在回到大多数情况下等价于的问题,我们会发现,当 \(S'[i,i+2l-1]=S'[2*n-(i+2l-1)+1,2*n-i+1]\) 的时候,它也可能有 \(rk_i<rk_{2*n-(i+2l-1)+1}\)。考虑怎么减去这种情况。

如果 \(S'[i,i+2l-1]=S'[2*n-(i+2l-1)+1,2*n-i+1]\),就说明 \(S[i,i+2l-1]\) 是一个回文串,如果以 \(i+l+\frac{1}{2}\) 这个回文中心向外延伸,第一次不同的两个字符满足 \(c_{i+l+j-1}<c_{i+l-j}\),则就会出现 \(rk_i<rk_{2*n-(i+2l-1)+1}\),这个东西可以用 manacher 找出来,并再做一次扫描线求解。

时间复杂度 \(O(n\log n)\)。

Day2 T3 合并书本

有 \(n\) 堆书本,每一堆书本有两个参数 \((w_i,d_i)\),初始时 \(w_i\) 给定,\(d_i=0\)。你需要进行 \(n-1\) 次合并,如果合并 \((w_1,d_1)\) 和 \((w_2,d_2)\),则会消耗 \(w_2+d_1+d_2\) 的代价,得到一堆参数为 \((w_1+w_2,2\max(d_1,d_2)+1)\) 的书,要求最小化代价和。

发现合并的过程是一棵二叉树,对于 \(w\) 数组造成的代价,是每一个叶子节点到根的过程中作为右孩子的次数;对于 \(d\) 数组造成的贡献 \(D\),只与树形态有关。

对于一棵二叉树,我们确定了每一个叶子在代价中的系数 \(a_i\),则我们将所有的书本的 \(w\) 从小到大排序,所有的 \(a\) 从大到小排序,同时对位相乘即可。

现在的问题是我们要如何求出这个系数可重集 \(S\) 和 \(D\) 的关系。

考虑每次将若干叶子分裂的过程,那么我们会将集合中的若干个 \(x\) 变成 \(x\) 和 \(x+1\)。根据贪心策略可以得到,我们必然选择前若干小的叶子分裂。

但是这个时候我们发现 \(D\) 并不是很好计算,考虑如何维护分裂,反转成为合并考虑:每一次删去所有的叶子,每一次删除的叶子树是逐渐减少的。

所以考虑钦定分裂的叶子数 \(t\),每一次分裂的叶子数量不会减少。这样每一次所有非叶子节点的代价都会 \(\times 2-1\),所以可以直接计算。

发现这样的搜索十分优秀,可以通过此题。

代码

NOI 2023 题解的更多相关文章

  1. HDU 2023题解分析

    我想说这道题我还没弄明白我错哪了,交了20多遍一直都是Runtime Error,改了N次还是不对,后来搜了一下,说是数组开小了,又把数组开大,还不对,又改发现一个平均值求错,再改,还不对,洗洗睡吧. ...

  2. 【题解】NOI 系列题解总集

    每次做一道 NOI 系列的估计都很激动吧,对于我这种萌新来说( P1731 [NOI1999]生日蛋糕 练习剪枝技巧,关于剪枝,欢迎看我的垃圾无意义笔记 这道题是有一定难度的,需要运用各种高科技剪枝( ...

  3. 【noi openjudge题解】最低通行费

    这道题完全没有必要去计算限制时间,把时间当做一个参数来做就行了.知道了这一点之后就可以直接使用DP求解了 #include <algorithm> #include <iostrea ...

  4. NOI Online 题解

    T1 对\(t_i = 1\)的边,将\(u_i, v_i\)连一条边权为\(1\)的边.否则连一条边权为\(0\)的边. 对于每一个连通块,若图中不存在一条边权之和为奇数的圈,则可以将这个连通块二染 ...

  5. POJ1185 炮兵阵地 —— 状压DP

    题目链接:http://poj.org/problem?id=1185 炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions ...

  6. NOI题库刷题日志 (贪心篇题解)

    这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制:  1000ms  内存限制:  65536kB 描述 在一个平面上,如果有两个点( ...

  7. NOI题库 1768最大子矩阵 题解

    NOI题库 1768最大子矩阵  题解     总时间限制: 1000ms 内存限制: 65536kB   描述   已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大 ...

  8. 【NOI 2019】同步赛 / 题解 / 感想

    非常颓写不动题怎么办…… 写下这篇博客警示自己吧…… 游记 7.16 我并不在广二参加 NOI,而是在距离广二体育馆一公里远的包间打同步赛(其实就是给写不动题找个理由) 上午身体不舒服,鸽了半天才看题 ...

  9. NOI 2021 部分题目题解

    最近几天复盘了一下NOI 2021,愈发发觉自己的愚蠢,可惜D2T3仍是不会,于是只写前面的题解 Day1 T1 可以发现,每次相当于将 \(x\to y\) 染上一种全新颜色,然后一条边是重边当且仅 ...

  10. [NOI导刊2010提高&洛谷P1774]最接近神的人 题解(树状数组求逆序对)

    [NOI导刊2010提高&洛谷P1774]最接近神的人 Description 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某 ...

随机推荐

  1. spring启动流程 (6完结) springmvc启动流程

    SpringMVC的启动入口在SpringServletContainerInitializer类,它是ServletContainerInitializer实现类(Servlet3.0新特性).在实 ...

  2. 08-避免Latch的产生

    1.Latch简介 Latch就是锁存器,是一种在异步电路系统中,对输入信号电平敏感的单元,用来存储信息 锁存器在数据未锁存时,输出端的信号随输入信号变化,就像信号通过一个缓冲器,一旦锁存信号有效,数 ...

  3. C++中vector容器详解

    参考链接:https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html 一.什么是vector? 向量(Vector)是一个封装了 ...

  4. 260. 只出现一次的数字 III

    1.题目介绍 2.题解 2.1 快排+遍历 思路 同本系列前几题一样 代码 class Solution { public: std::vector<int> singleNumber(s ...

  5. Laravel - 419 unknown status 解决

    在 head 头部加入下方代码就可解决<meta name="_token" content="{{ csrf_token() }}"/>

  6. [转帖]关于UNDO

    原文地址:https://www.modb.pro/db/70802?xzs= 一:请描述什么是Oracle Undo. 二:请描述UNDO的作用. 三:请谈谈你对Manual Undo Manage ...

  7. [转帖]strace分析sqlplus登录慢问题

    一. 问题分析 有时会遇到sqlplus / as sysdba登录非常慢的问题,由于还没登录,通过数据库等待事件一般看不出来啥,需要用到strace这个分析利器.strace有很多参数,后面会列出, ...

  8. [转帖]将 Cloudflare 连接到互联网的代理——Pingora 的构建方式

    https://zhuanlan.zhihu.com/p/575228941 简介 今天,我们很高兴有机会在此介绍 Pingora,这是我们使用 Rust 在内部构建的新 HTTP 代理,它每天处理超 ...

  9. WinSCP和xftp 从Windows 上传到linux服务器时出现中文乱码的解决方案

    1. 日常工作中有需求从Windows的办公机器将文件上传到linux服务器上面进行使用 中文经常出现乱码, 需要处理一下. 这里面主要用到了两个工具 WinSCP还有xftp 两个的原理都是一样的 ...

  10. Redis labs 的安装

    Install and setup This guide shows how to install Redis Enterprise Software, which includes several ...