CSP-S 2019 题解
D1T1-格雷码
题中给出了构造格雷码的方法。
$solve(n,k)$表示求出$2^n$意义下排名为$k$的格雷码,
只要比较一下考虑最高位的0/1取值就好了。
部分分提示了要开$unsigned\ long\ long$,注意一下就可以了。
D1T2-括号树
子序列问题是便于处理的,只要处理以每个点结尾的合法序列,作树上前缀和就好了。
然而合法括号序列也并不简单。
判断一个括号序列是否合法的方法是,
视左右括号分别为+1,-1。
判断是否满足前缀和不小于0,并且总和为0。
套用这个思路,考场上想到的一个做法是。
用一个multiset维护前缀和。
当加入一个左括号时插入元素,同时给set中所有元素作加一处理。
当加入一个右括号时不断删除set中最小的元素,即前缀小于0的不合法判断。
同时维护一个桶,记录set中元素的树上前缀和,这样可以做到O(1)直接查询合法的当前点为结尾的括号序列。
然而因为树上的特殊性质,set需要还原,在最坏的情况下(可以为扫把图),这个算法可以被卡到O(n^2logn)。
因为官方数据很水,它AC了。因为洛谷数据很水,它AC了。
因为牛客数据和清北学堂数据都并不水,它TLE80分。
正解实际上利用了一个点为结尾的合法括号序列的另一种生成方式,这在题目背景中也有提示。
找到最近的一个满足左括号数等于右括号数的点,在满足这一段合法的意义下,只要加上它前面一个点为结尾生成的合法括号序列数就好了。
一个简单的做法是用栈维护,左括号即压栈,右括号即弹出栈顶元素,同时可以确定第一个合法的位置。
D1T3-树上的数
大概是一个贪心。
一个点想要换到想要换到的点,限制了路径上每个点的一个交换顺序。
然后部分分看起来就很可打,链上只要维护左右的先后顺序,菊花只要搞一个类似并查集的插入的结构来确定先后顺序。
然后感觉分类讨论非常复杂,两个都没有打出来,只有10分暴力。
还没有改这道题。
D2T1-Emiya 家今天的饭
开始做这道题并没有思路,感觉十分不可做。
猜测复杂度,估计是$O(n^2m)$,所以要枚举菜?
然后突然想,这个玩意只要简单容斥就好了。
枚举最终不合法的菜是哪一道。
一个简单的做法是直接记录选了多少道菜和选了多少道非法的菜,这样直接$dp$的复杂度是$O(n^3m)$。
然而状态数太多了,所以可以想到记录差值,即非法的菜数 - 选的菜数/2,同时维护选的菜数的奇偶性,
然后复杂度就对了,然后就因为没打取模优化成功被卡常了。
D2T2-划分
看到数据范围整懵了,没有任何思路。
然后发现暴力$dp$,$O(n^2)$就有64分了,所以直接打。
$dp(l,r)$表示最后一次选择的区间,显然转移点是一个后缀,
只要用单调指针预处理出这个后缀的位置,直接取后缀最小值就好了。
正解有一个贪心,只要满足最后一次选的区间最小,答案就是最小的。
并不会证明,然而直观理解一下是正确的。
设$f_x$表示$x$结尾的最小的最后一次选择的区间,有简单的转移
$f_i=min_j(pre_i-pre_j)(pre_i-pre_j>=f_j)$,这个玩意的形式还挺简单的,
顺便记录一下答案就做到$O(n^2)$了,弱智剪枝是找到第一个答案直接跳出,在一些比较水的数据下可以得到84分。
然后发现这个转移的条件是$pre_i-pre_j>=f_j$,即$pre_i>=f_j+pre_j$,因为$pre$数组是单调的,所以显然转移点也是单调的。
然后用一个单调队列维护一下就好了。
因为数据范围过大,需要写高精度。
为了防止$MLE$,可以在转移的同时不记录答案而是维护转移点。
最后统计一下答案就好了。
D2T3-树的重心
看题发现部分分有75,而且蛮好打的。
暴力和链可以直接打出来。
对于满二叉树,打个表就发现答案只出现在根节点和它的两个儿子的系数是2的一个次幂,其它节点的系数都是1。
考试最后几分钟大概想到了答案一定只出现在重链上。
所以维护重链,同时二分答案就可以了,当然比较简单的做法是用倍增来实现这个二分的过程。
然而并不会维护父亲方向的重链,实际上是一个简单的换根$dp$,难度并不是很大。
在计算的过程中多打几个特判就好了。
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+;
int n,tot=;
int head[N],nxt[N<<],to[N<<];
int sz[N],son[N],son2[N];
int f[N][];
long long ans;
void dfs1(int x,int fa){
sz[x]=;
for(int i=head[x];i;i=nxt[i]) if(to[i]!=fa){
dfs1(to[i],x);
sz[x]+=sz[to[i]];
if(sz[to[i]]>sz[son[x]]) son2[x]=son[x],son[x]=to[i];
else if(sz[to[i]]>sz[son2[x]]) son2[x]=to[i];
}
f[x][]=son[x];
for(int i=;i<=;++i) f[x][i]=f[f[x][i-]][i-];
}
int solve(int x){
if(!son[x]) return x;
int now=x,ans=;
for(int i=;~i;--i) if(sz[x]-sz[f[now][i]]<sz[x]/) now=f[now][i];
if(sz[son[now]]<=sz[x]/&&sz[x]-sz[now]<=sz[x]/) ans+=now;
now=son[now];
if(sz[son[now]]<=sz[x]/&&sz[x]-sz[now]<=sz[x]/) ans+=now;
return ans;
}
void dfs2(int x,int fa){
for(int i=head[x];i;i=nxt[i]) if(to[i]!=fa){
int tmp=son[x],s=sz[x];
sz[x]=n-sz[to[i]];
if(to[i]==son[x]) son[x]=son2[x];
if(fa&&sz[fa]>sz[son[x]]) son[x]=fa;
f[x][]=son[x];
for(int j=;j<=;++j) f[x][j]=f[f[x][j-]][j-];
ans+=solve(to[i]);
ans+=solve(x);
dfs2(to[i],x);
son[x]=tmp; sz[x]=s; f[x][]=son[x];
for(int j=;j<=;++j) f[x][j]=f[f[x][j-]][j-];
}
}
inline void add(int a,int b){
nxt[++tot]=head[a]; to[head[a]=tot]=b;
nxt[++tot]=head[b]; to[head[b]=tot]=a;
}
inline int read(register int x=,register char ch=getchar(),register int f=){
for(;!isdigit(ch);ch=getchar()) f=ch=='-';
for(; isdigit(ch);ch=getchar()) x=(x<<)+(x<<)+(ch^);
return f?-x:x;
}
int main(){
freopen("centroid.in","r",stdin);
freopen("centroid.out","w",stdout);
int T=read();
while(T--){
tot=; ans=;
memset(head,,sizeof(head));
memset(son,,sizeof(son));
memset(son2,,sizeof(son2));
n=read();
for(int i=;i<n;++i) add(read(),read());
dfs1(,); dfs2(,);
printf("%lld\n",ans);
}
return ;
}
CSP-S 2019 题解的更多相关文章
- 上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解
前 言: 一直很想写这道括号树..毕竟是在去年折磨了我4个小时的题.... 上午小测3 T1 括号序列 前言: 原来这题是个dp啊...这几天出了好几道dp,我都没看出来,我竟然折磨菜. 考试的时候先 ...
- Hello 2019题解
Hello 2019题解 题解 CF1097A [Gennady and a Card Game] map大法好qwq 枚举每一个的第\(1,2\)位判是否与给定的重复即可 # include < ...
- ICPC World Finals 2019 题解
[A]Azulejos 题意简述: 有两排瓷砖,每排都有 \(n\) 个,每个瓷砖有高度 \(h_i\) 和价格 \(p_i\) 两种属性. 你需要分别重新排列这两排瓷砖,使得同一排的瓷砖满足价格不降 ...
- Code Chef February Challenge 2019题解
传送门 \(HMAPPY2\) 咕 话说这题居然卡\(scanf\)的么??? int T;cin>>T; while(T--){ cin>>n>>a>> ...
- CodeChef March Challenge 2019题解
传送门 \(CHNUM\) 显然正数一组,负数一组 for(int T=read();T;--T){ n=read(),c=d=0; fp(i,1,n)x=read(),x>0?++c:++d; ...
- @CSP模拟2019.10.16 - T3@ 垃圾分类
目录 @description@ @solution@ @accepted code@ @details@ @description@ 为了保护环境,p6pou建设了一个垃圾分类器. 垃圾分类器是一个 ...
- Code Chef April Cook-Off 2019题解
传送门 \(PEWDSVTS\) 我哪根筋不对了要把所有可行的拿出来\(sort\)一下--还有忘开\(long\ long\)真的好难受-- int main(){ // freopen(" ...
- Atcoder Tenka1 Programmer Contest 2019 题解
link 题面真简洁 qaq C Stones 最终一定是连续一段 . 加上连续一段 # .直接枚举断点记录前缀和统计即可. #include<bits/stdc++.h> #define ...
- Atcoder Tenka1 Programmer Contest 2019题解
传送门 \(C\ Stones\) 最后肯定形如左边一段白+右边一段黑,枚举一下中间的断点,预处理一下前缀和就可以了 int main(){ // freopen("testdata.in& ...
- Code Chef January Challenge 2019题解
传送门 \(div2\)那几道题不来做了太水了-- \(DPAIRS\) 一个显然合法的方案:\(A\)最小的和\(B\)所有连,\(A\)剩下的和\(B\)最大的连 算了咕上瘾了,咕咕咕 const ...
随机推荐
- Codechef November Challenge 2019 Division 1
Preface 这场CC好难的说,后面的都不会做QAQ 还因为不会三进制位运算卷积被曲明姐姐欺负了,我真是太菜了QAQ PS:最后还是狗上了六星的说,期待两(三)场之内可以上七星 Physical E ...
- flask--数据库迁移之连环踩坑记
flask数据库迁移命令: python manage.py db init python manage.py db migrate python manage.py db upgrade 1.报错: ...
- js实现addClass方法,classList与className有什么区别?
壹 ❀ 引 Jquery中addClass与removeClass是两个使用高频的方法,对于为dom元素增删class类非常方便:但如果不用JQ,使用js怎么模拟它们呢?本文主要记录下自己的实现思路 ...
- MySQL数字类型学习笔记
数字类型 最近在看<MySQL技术内幕:SQL编程>并做了笔记,所以本博客是一篇笔记类型博客,分享出来方便自己复习,也可以帮助他人 整型 类型 占用空间 最小值(SIGNED) 最大值(S ...
- onunload事件不触发的探索
如果现有一需求:浏览器页面关闭时弹出一个对话框,询问是否要退出,应该怎么做呢? 可用onunload事件来实现,该事件会在刷新和关闭页面时执行 我用如下3种方法绑定该事件,但所有主流浏览器都无法 ...
- Linux常用命令之网络命令
write命令 write命令用于向指定登录用户终端上发送信息.通过write命令可传递信息给另一位登入系统的用户,当输入完毕后,键入EOF表示信息结束,write命令就会将信息传给对方.如果接收信息 ...
- Java内功心法,Set集合的详解
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- Python分页爬取数据的分析
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 向右奔跑 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- python web框架Flask——后台登录
项目搭建 创建一个项目之后,需要在手动创建几个包(含有__init__.py文件的目录)和文件 1.在主目录下创建配置文件:config.py 2.在主目录下创建扩展文件:exts.py 3.在主目录 ...
- Cygwin添加右键菜单
修改注册表 统一的方式,添加一个右键命令 找到HKEY_CLASSES_ROOT\Directory\Background\shell 右键,新建项.名字随便起 再次右键,新建项.命名command ...