CSP-S2019题解
格雷码
€€£:我不抄自己辣!JOJO!
这题比那个SCOI的炒鸡格雷码好多了,甚至告诉你构造方法,所以...
void wk(uLL kk)
{
int j=0;
for(uLL i=n-1;~i;--i)
{
if(kk>>i&1) printf("%d",j^1),j^=j==0;
else printf("%d",j),j^=j==1;
}
}
括号树
考虑朴素做法,即dfs整棵树,然后记录到根的括号序列,每个点的贡献为祖先贡献+以自己这个位置为右端点的合法括号序列数量,可以\(O(n^2)\)
考虑优化,我们要统计的括号序列是一段后缀,所以把)
看做\(1\),(
看做\(-1\),那么一个后缀为合法括号序列当且仅当这一段的权值和为0,且这个后缀没有包含一段和\(<0\)的后缀(也就是有一些(
一定匹配不上)
),那么线段树每个位置维护对应后缀的和,以及再维护区间权值0个数(就是维护区间最小值以及其个数),每次进入一个点先对所有后缀\(+1/-1\),然后线段树上二分找出权值\(<0\)的最靠右位置\(p\),那么以这个点为最右端的合法括号序列个数就是\([p+1,dep_x]\)内权值0个数
M_sea:你个[],这不是\(O(n)\)傻[]题吗
其实线段树是多余的,考虑对种和开一个桶记录这种权值的数出现次数,然后每次加入一个点就看这个点导致的整个权值变化,再用当前权值意义下为0的桶更新答案,不过要注意在之前当前权值意义下为-1的最后一个数不能计入答案,所以在更新桶的时候注意一下(ruaaa)
树上的数
wtcl,又被这种题送退役了
做法显然是从小到大枚举每个数,然后枚举这个数最终走到的点,如果合法就让它走过去,现在问题是怎么判断合法
考虑一个数从点\(x\)走到\(y\),依次经过的边为\(e_1,e_2...e_m\),首先\(e_1\)必须比其他和\(x\)相连的边先选(如果前面已经有一些必须在最前面的边,就把\(e_1\)放在前面那些边的最后面),否则这个数会走到别的地方去,并且走不回来,然后中间的\(e_i(1<i\le m)\),一定是比\(e_{i-1}\)后选,并且对于和\(e_{i-1}\)和\(e_i\)公共点相连的其他边,都不能在\(e_{i-1}\)和\(e_i\)之间选.最后是\(e_m\),必须在其他和\(y\)相连的边选完后再选(如果后面已经有一些必须在最后面的边,就把\(e_m\)放在后面那些边的最前面),不然这个数会跑到别的地方去
这里面比较麻烦的是中间那个其他边不能在两条边之间选,但如果我们只考虑一个点以及它连出去的边(相当于菊花图),这个时候我们发现其他不连接这个点的边是不会影响到这个点上的数的,也就是一个点连出去的菊花是和其他菊花互不影响的,那么可以先单独考虑最后放在一起看.对于一个菊花,如果要使得其他边不能在两条边之间选,那么这两条边必须选完前面一条后马上选另一条.那么上述限制可以抽象成:一条边必须最先选,一条边必须最后选,两条边必须选完一条后马上选另一条.那么可以对每个点建一个链表,维护这些边操作的相对顺序,一条边必须在前面就建一个表示最前面的虚点,然后这条边接在这个虚点链尾后面;一条边必须在最后类似;一条边必须在另一条边后操作,那就把这两条边所在链接在一起.至于一些矛盾关系,这里简单列举一下:
- 接完以后会出现环(无向图意义上的环)或者链上有分叉
- 最前面虚点必须为链首,最后面虚点必须为链尾
- 接完以后使得最前面虚点为链首,最后面虚点为链尾,但是还有其他不在这一条链上的一些链
Emiya 家今天的饭
这里的方案计算只有某一列被选次数不超过\(\lfloor\frac{k}{2}\rfloor\)这个限制不太好直接做,所以考虑容斥,即总方案-不合法方案.总方案为\(\prod_{i=1}^{n}(1+\sum_{j=1}^{m}a_{i,j})\)
如果有一列被选次数\(>\lfloor\frac{k}{2}\rfloor\),那么有且仅有这一列会超出限制,所以不合法方案只有一列不满足限制,那就枚举超出限制的为哪一列,然后设\(f_{i,j,k}\)表示考虑前\(i\)行,选了\(j\)次,指定的不合法列选\(k\)次的方案,转移背包转移即可,那么这一列的贡献为\(\sum_{j=1}^{n}\sum_{k=\lfloor\frac{j}{2}\rfloor+1}^{j} f_{n,j,k}\),复杂度\(O(n^3m)\)
考虑优化,如果我们把上述状态的\(j-k\)和\(k\)做差,那么一个不合法方案,它的这个差一定\(<0\),所以上述状态改为\(f_{i,j}\)表示前\(i\)行,其他列出现次数-指定列出现次数为\(j\)的方案,然后转移完后用\(j<0\)的统计,即可做到\(O(n^2m)\).实现时注意负下标的处理
划分
先考虑朴素dp,设\(f_{i,j}\)表示上一次选择的段为\([j,i]\)的最小值,复杂度\(O(n^3)\),然后注意到一个\(f_{i,j}\),从前面一个位置\(k\)转移过来\((k=j-1)\),那么\(f_k\)的合法第二维一定是在\([x,k]\)之间,其中\(x\)为最大的能转移到\(f_{i,j}\)的位置,那么记一下\(f_{i,j}\)关于\(j\)的后缀最小值,即可做到\(O(n^2)\)
然后先丢一个证明链接,再不加证明的给出两个引理
- 一个\(f_{i,j}\)往后转移时,一定是用合法的\(j\)最大的\(f_{i,j}\)的转移到后面,后面记这个最大的\(j\)为\(p_i\)
- 对于一个\(i\),记能从前面转移过来的位置集合为\({x}\),那么最优的转移位置一定是集合最大值\(k\),即用\(f_{k,p_k}\)转移到\(f_{i,k+1}\)
你问我为什么不给证明,因为这是打表得到的
这样对于每个\(i\),二分出它最先可以贡献的后面的位置(即最小的\(a\)满足\(sum_a-sum_i\ge sum_i-sum_{p_i-1}\)),把\(i\)丢进对应的决策集合,然后在做到某个位置时用这个位置的决策更新最优决策,可以做到\(O(nlogn)\)
但这个二分是可以去掉的,我们维护一个单调队列,维护还没加入的决策\(i\),这些\(i\)以对应的\(sum_i-sum_{p_i-1}\)为关键字,每次加入一个决策进队列就把队尾的一定比这个决策差的决策弹掉(设队尾对应元素为\(t\)即\(sum_i-sum_{p_i-1}<=sum_t-sum_{p_t-1}-(sum_i-sum_t)\)时弹队尾),然后压进队尾,每次用队首能加入的决策更新当前决策
同时你还需要实现一个高精,所以请注意常数问题.我这里用的是4个\(\text{int}\)表示\(32\)位整数
树的重心
初赛时认为完全二叉树就是满二叉树,然后这道题以为完美二叉树不是满二叉树,就GG QAQ
考虑朴素做法,枚举鸽的是哪条边,然后对于剩下两个子树分别求重心,具体操作是分别以两个点为根,然后从根出发,走到第一个点满足最大的儿子子树大小\(\le \lfloor\frac{size}{2}\rfloor\).如果有两个重心,则说明当前走到的点最大的儿子子树大小\(=\lfloor\frac{size}{2}\rfloor\),那么另一个重心为对应子树大小最大的儿子
如果套用以上做法,然后随便设一个点为根,那么可以统计出鸽掉每条边后,靠下面的点(记为\(y\))的子树的重心贡献,在往儿子走的时候加一个倍增优化即可.然后还有被鸽边上面那个点(记为\(x\))的贡献,那么可以看做是把\(x\)作为根,然后不考虑\(y\)的子树,然后往儿子走的过程,所以可以考虑换根dfs,因为在dfs到某个点的时候,只有这个点到根路径上的点的父子关系变化了,所以每次枚举这个点的儿子\(y\)时,\(x\)为根时的儿子实际上是\(x\)在原树中的其他儿子和\(x\)的父亲,那么倍增数组只要用这些\(x\)为根时的儿子预处理就好了.具体实现的时候,如果\(y\)为子树大小最大的儿子,那么\(x\)下一步走的是父亲或者子树大小次大儿子,否则是父亲或者子树大小最大儿子
CSP-S2019题解的更多相关文章
- 上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解
前 言: 一直很想写这道括号树..毕竟是在去年折磨了我4个小时的题.... 上午小测3 T1 括号序列 前言: 原来这题是个dp啊...这几天出了好几道dp,我都没看出来,我竟然折磨菜. 考试的时候先 ...
- [CSP模拟测试43、44]题解
状态极差的两场.感觉现在自己的思维方式很是有问题. (但愿今天考试开始的一刻我不会看到H I J) A 考场上打了最短路+贪心,水了60. 然而正解其实比那30分贪心好想多了. 进行n次乘法后的结果一 ...
- 题解 nflsoj489 【六校联合训练 CSP #15】小D与随机
题目链接 考虑枚举好点的集合.此时要考虑的问题是如何填入\(1\sim n\)这些数使得恰好我们枚举到的这些点是好点,即:求出有多少种合法的填数方案. \(1\)号点一定是好点.那么除\(1\)号点外 ...
- CCF CSP 201703-3 Markdown
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-3 Markdown 问题描述 Markdown 是一种很流行的轻量级标记语言(l ...
- CCF计算机职业资格认证考试题解
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF计算机职业资格认证考试题解 CCF计算机软件能力认证(简称CCF CSP认证)是CCF计算机职业资格认证系 ...
- CCF CSP 201312-3 最大的矩形
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201312-3 最大的矩形 问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i( ...
- CCF CSP 201609-3 炉石传说
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201609-3 炉石传说 问题描述 <炉石传说:魔兽英雄传>(Hearthston ...
- CCF CSP 201403-3 命令行选项
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201403-3 命令行选项 问题描述 请你写一个命令行分析程序,用以分析给定的命令行里包含哪些 ...
- CCF CSP 201709-4 通信网络
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201709-4 通信网络 问题描述 某国的军队由N个部门组成,为了提高安全性,部门之间建立了M ...
- CCF CSP 201409-3 字符串匹配
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201409-3 字符串匹配 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那 ...
随机推荐
- CloudFlare 新手入门中文教程
loudFlare成立于2009年,是国外著名的免费CDN网站加速服务公司,CloudFlare 还提供实时安全保护服务和网络优化等,采用的是免费+增值模式,可以免费使用,也有收费服务.国内也有很多免 ...
- NiewPatchDrawable
在使用AS的时候要注意以下几点: 1.点9图不能放在mipmap目录下,而需要放在drawable目录下! 2.AS中的.9图,必须要有黑线,不然编译都不会通过 xml定义NinePatchDrawa ...
- WPF 设置TextBox为空时,背景为文字提示。
<TextBox FontSize="> <TextBox.Resources> <VisualBrush x:Key="HelpBrush" ...
- eNSP V100R002C00B500 Setup模拟CE6800
本人操作系统:Windows7 64 下载需要的安装包: eNSP V100R002C00B500 官网下载地址:点击这里 CE6800 官网下载地址:点击这里 USG6000V ...
- Java 实现 telnet命令 验证主机端口的连通性
Java 实现 telnet命令 验证主机端口的连通性 1.Telnet 命令 Telnet协议是TCP/IP协议族中的一员,是Internet远程登录服务的标准协议和主要方式.它为用户提供了在本地计 ...
- 打印Linq生成的SQL语句
var t1 = source.OrderBy<T>(orderby).Skip<T>(_skip).Take<T>(_take); var t2 = t1.ToO ...
- [C++/JavaScript]数据结构:栈和数列>案例引入(数制的转换)
1 案例1:数制的转换 1.1 背景与原理 1.2 编程复现 (JavaScript版 复现) function convert(value, d){ stack = []; // 栈 result ...
- nginx访问日志的几个统计命令
nginx日志中得到访问量最高前10个IP: cat access.log.10 | awk '{a[$1]++} END {for(b in a) print b"\t"a[b] ...
- Linux学习笔记:vim
目录 模式 命令模式 编辑模式 底行模式 .vimrc .viminfo .swap 本文更新于2019-09-05. 说明:下文中,使用{}引起表示自定义变量,根据实际情况填写.使用[]引起表示内容 ...
- Java工程师学习指南第2部分:JavaWeb技术世界
本文整理了微信公众号[Java技术江湖]发表和转载过的Java Web优质文章,想看到更多Java技术文章,就赶紧关注吧. IDEA中的Maven实战 老师,免费版的IDEA为啥不能使用Tomcat? ...