「模拟赛」暑期集训CSP提高模拟4(7.21)
很祭的一次比赛,啥也不会。
题目列表:
A.White and Black
\(0 pts\)
题意:
给你一颗树,树根为 1 ,初始所有点都是白色,每次询问给出一个点集,若把点集中的点全部染成黑色,问至少需要翻转多少个节点才能使整棵树全为白点。无解输出 -1。询问之间相互独立
翻转的定义为:将节点 u 及其子树中所有节点颜色翻转。
赛时分析:
赛时不会,想到了时间复杂度 \(O(n * m)\) 的树上 DP,以为是正解(时间复杂度想假了 \(n\) 按 \(log\large{n}\) 算的),打完才发现时间复杂度不对,之后就只想着怎么在这个基础上优化了,一直在思考把 \(n\) 变成 \(log \large{n}\),本地跑大样例从 \(36s\) 卡常优化到了 \(1.9s\),但时间复杂度没变,大概调了一个多小时急了,直接交了,想着能拿个 \(30pts\),特殊性质也没想,结果捆绑测试实际得分 \(0pts\)。
以后模拟赛不能一个思路耗死,不能太高估自己,像这个题,性质也没那么难想,但自己完全就是没想着会有什么性质,一直在优化自己的 dp,看来以后要及时否定自己多换思路。
正解:
注:下文“染黑某个点”等说法皆指染黑以该点为根的子树。
思想:
我们枚举每个被染黑的点,设为 \(u\),由于 \(u\) 已经被染黑了,所以我们肯定要把它染回来,如果 \(u\) 的父亲节点 \(fa\) 也为黑点,那么我们在进行将 \(fa\) 染为白点的操作后,自然也一起把 \(u\) 染白了;
再枚举 \(u\) 的子节点 \(son\),如果 \(son\) 为白色,那么在把 \(u\) 染回来的操作中,\(son\) 点便被染黑了,所以还需要再染一次 \(son\) 点。
计算答案 \(ans\) 时,那么我们只需遍历每个被染黑的点,若它的父亲节点不是黑点,则需要染一次,\(ans++\),再遍历它的子节点,若子节点是白点,则还需染子节点一次,\(ans++\)。
这便是我们的思想,不过较容易发现,时间复杂度为 \(O(Q n m)\),(\(Q\) 为询问的次数),会 \(T\) 掉。
暴力代码
#include<bits/stdc++.h>
#define mp make_pair
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n, Q, m, in[N];
int color[N], fa[N];
map<pair<int, int>, int>son;
signed main(){
// freopen("in.in", "r", stdin); freopen("a.out", "w", stdout);
scanf("%d%d", &n, &Q);
for(int i=2; i<=n; i++){
scanf("%d", &fa[i]);
son[mp(fa[i], ++son[mp(fa[i], 0)])] = i;
}
while(Q--)
{
scanf("%d", &m);
for(register int i=1; i<=m; i++){
scanf("%d", &in[i]);
color[in[i]] = 1;
}
int ans = 0;
for(int i=1; i<=m; i++){
if(!color[fa[in[i]]]) ans++;
for(int j=1; j<=son[mp(in[i], 0)]; j++){
if(!color[son[mp(in[i], j)]]) ans++;
}
}
printf("%d\n", ans);
for(register int i=1; i<=m; i++) color[in[i]] = 0;
}
return 0;
}
考虑优化:
时间复杂度多的那个 \(n\) 是枚举每个黑点的儿子节点导致的,所以我们考虑能不能不枚举每个儿子,我们可以预处理出来的时每个节点儿子的数量,这些数量是不会变化的,“别管黑儿子还是白儿子都是儿子”。
所以在枚举每个黑点的时候,我们可以直接加上该点儿子的数量。但这样就多加了黑儿子啊,按照我们的思路只加白儿子,但别忘了,黑儿子是被染黑的点,所以我们枚举所有黑点时总会枚举到这些多加的黑儿子,那么我们枚举时,判断枚举点的父亲节点是否为黑,若为父亲节点为白,则加一次操作,否则把减去一次操作,这样就把多加的黑儿子减去了。
成功优化到 \(O(Q n)\) 了!
最终代码:
#include<bits/stdc++.h>
#define mp make_pair
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n, Q, m, in[N];
int color[N], fa[N], son[N];
signed main(){
// freopen("in.in", "r", stdin); freopen("a.out", "w", stdout);
scanf("%d%d", &n, &Q);
for(int i=2; i<=n; i++){
scanf("%d", &fa[i]);
son[fa[i]]++;
}
while(Q--)
{
scanf("%d", &m);
for(register int i=1; i<=m; i++){
scanf("%d", &in[i]);
color[in[i]] = 1;
}
int ans = 0;
for(int i=1; i<=m; i++){
if(!color[fa[in[i]]]) ans++;
else ans--;
ans += son[in[i]];
}
printf("%d\n", ans);
for(register int i=1; i<=m; i++) color[in[i]] = 0;
}
return 0;
}
White and White
题意:
怀特有一个长度为 \(n\) 的正整数数列 \(A\) ,现在他在研究一种数列划分方法。
划分是将这个这个数列分成 \(k\) 个非空连续段,每段的价值为这段所有数的总和对给定的怀特数 \(p\) 取模后的值。
使得这 \(k\) 段的价值总和最小的划分方法就被成为怀特划分法。
Black and Black
题意:
布莱克现在有一个长度为 \(n\) 的序列 \(A\),但是由于他的 dp 不好,所以 \(A\) 序列只会出现 1,−1 这两个数,虽然他也不知道这有什么用,但是需要 dp 的时候这样会变简单吧
为了给以后的 dp 做更多准备,现在他想求出一个布莱克序列 \(B\) ,布莱克序列 \(B\) 满足以下几个限制
- 序列长同样为 \(n\)
- \(∣Bi∣≤2×10^{12};\)
- 序列严格递增,即 \(∀1≤i<n,Bi<Bi+1\);
- \(∑_{i=1}^nAiBi=0\)。
给定一个序列,求是否是布莱克序列。
赛时分析:
其实赛时基本想到正解了,但由于在 T2 卡的时间过长,所以 T3 根本没敢仔细想即使是已经出现正解的思路,只是在最后半小时打完了 T3 和 T4 的暴力。
正解:
构造。我们先将 \(b_i\) 赋值为 \(i\),并求 \(∑_{i=1}^n b_i * a_i\) 的和记为 \(sum\),求一个 \(s\) 数组为 \(a\) 数组的前缀。
若 \(sum=0\) 直接输出即可
\(sum>0\) 时
- 从头到尾扫一遍 \(s\),找到第一个 \(s_i>0\) 的情况,(由于是第一个,那么一定有找到的 \(s_i=1\) )那么说明我们可以把 \(b_j(j\in[1, i])\) 都减去 \(sum\),等价于整个 \(b\) 数组的总和减去了 \(sum\),那么总和就为 0 了;
- 若未扫到,那再从尾到头再扫一遍,找到第一个 \(s_n - s_i<0\) 的情况(同理 \(s_n-s_i=-1\)),这样我们把 \(b_j (j\in[i, n])\) 全都加上 \(sum\) 即可;
- 还是找不到的话,那么说明无解,输出 -1。
\(sum<0\) 时,与上述相反操作即可。
code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10;
int n, a[N]; ll b[N], sum;
ll s[N];
inline void print(){
puts("Yes");
for(int i=1; i<=n; i++) printf("%lld ", b[i]);
}
int main(){
// freopen("in.in", "r", stdin); freopen("out.out", "w", stdout);
scanf("%d", &n);
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
s[i] = s[i-1] + a[i];
b[i] = i; sum += i * a[i];
}
if(sum == 0) print();
else if(sum < 0){
for(int i=n; i>=1; i--){
if(s[n] - s[i-1] > 0){
for(int j=i; j<=n; j++){
b[j] += -sum;
}
print();
return 0;
}
}
for(int i=1; i<=n; i++){
if(s[i] - s[0] < 0){
for(int j=1; j<=i; j++){
b[j] += sum;
}
print();return 0;
}
}
puts("No");
}
else{
for(int i=n; i>=1; i--){
if(s[n] - s[i-1] < 0){
for(int j=i; j<=n; j++)
b[j] += sum;
print();
return 0;
}
}
for(int i=1; i<=n; i++){
if(s[i] - s[0] > 0){
for(int j=1; j<=i; j++)
b[j] -= sum;
print();
return 0;
}
}
puts("No");
}
return 0;
}
Black and White
题意:
给你一颗树,边长均为1,初始所有点都是黑色,有以下两种操作:
C u
将点 \(u\) 的颜色反转,即黑变白,白变黑;G
询问距离最远的两个黑点的距离;
对于每一个操作 G,输出一个整数,表示最远的两个黑点的距离。
还不会...
「模拟赛」暑期集训CSP提高模拟4(7.21)的更多相关文章
- #10471. 「2020-10-02 提高模拟赛」灌溉 (water)
题面:#10471. 「2020-10-02 提高模拟赛」灌溉 (water) 假设只有一组询问,我们可以用二分求解:二分最大距离是多少,然后找到深度最大的结点,并且把它的\(k\)倍祖先的一整子树删 ...
- #10470. 「2020-10-02 提高模拟赛」流水线 (line)
题面:#10470. 「2020-10-02 提高模拟赛」流水线 (line) 题目中的那么多区间的条件让人感觉极其难以维护,而且贪心的做法感觉大多都能 hack 掉,因此考虑寻找一些性质,然后再设计 ...
- 「CSP-S模拟赛」2019第四场
「CSP-S模拟赛」2019第四场 T1 「JOI 2014 Final」JOI 徽章 题目 考场思考(正解) T2 「JOI 2015 Final」分蛋糕 2 题目 考场思考(正解) T3 「CQO ...
- 「NOIP模拟赛」数位和乘积(dp,高精)
统计方案数,要么组合数,要么递推(dp)了. 这是有模拟赛历史以来爆炸最狠的一次 T1写了正解,也想到开long long,但是开错了地方然后数组开大了结果100->0 T3看错题本来简单模拟又 ...
- 「Vijos 1284」「OIBH杯NOIP2006第二次模拟赛」佳佳的魔法阵
佳佳的魔法阵 背景 也许是为了捕捉猎物(捕捉MM?),也许是因为其它原因,总之,佳佳准备设计一个魔法阵.而设计魔法阵涉及到的最关键问题,似乎就是那些带有魔力的宝石的摆放-- 描述 魔法阵是一个\(n ...
- 「CSP-S模拟赛」2019第二场
目录 T1 Jam的计数法 题目 考场思路(正解) T2 「TJOI / HEOI2016」排序 题目 考场思路(假正解) 正解 T3 「THUWC 2017」随机二分图 题目 考场思路 正解 这场考 ...
- 「CSP-S模拟赛」2019第一场
目录 T1 小奇取石子 题目 考场思路 正解 T2 「CCO 2017」专业网络 题目 考场思路 题解 T3 「ZJOI2017」线段树 题目 考场思路 正解 这场考试感觉很奇怪. \(T1.T2\) ...
- 「2019-8-13提高模拟赛」树 (tree)
传送门 Description 你有一个 \(n\)个点的树,第 \(i\)个点的父亲是\(p_i\).每个点有一个权值 \(t_i\) 和一个颜色黑或者白.所有点一开始都是白色. 你要进行 \(m\ ...
- 「2019-8-11提高模拟赛」女装盛宴 (flag)
传送门 Solution 基环树+倍增+双指针 第一次因为#define int long long而玄学RE 为什么标程都不用开\(long long\)啊 Code /*玄学RE 看来defi ...
- 「CSP-S模拟赛」2019第三场
目录 T1 「POI2007」山峰和山谷 Ridges and Valleys 题目 考场思路(几近正解) 正解 T2 「JOI 2013 Final」 现代豪宅 题目 考场思路(正解) T3 「SC ...
随机推荐
- k8s中的pod更新策略
StatefulSet(有状态集,缩写为sts)常用于部署有状态的且需要有序启动的应用程序,比如在进行SpringCloud项目容器化时,Eureka的部署是比较适合用StatefulSet部署方式的 ...
- vue3项目安装依赖报错 npm ERR! code ERESOLVE
vue3项目安装依赖报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While reso ...
- Linux扩展篇-shell编程(十)-shell范式
shell编程提供一个范式,有利于统一程序风格,增加可读性. 范式: ASSIGN SHELL/指定壳 DESCRIPTION/程序说明 BODY/程序体 扩展: 1.ASSIGN SHELL/指定壳 ...
- INFINI Gateway 与华为鲲鹏完成产品兼容互认证
何为华为鲲鹏认证 华为鲲鹏认证是华为云围绕鲲鹏云服务(含公有云.私有云.混合云.桌面云)推出的一项合作伙伴计划,旨在为构建持续发展.合作共赢的鲲鹏生态圈,通过整合华为的技术.品牌资源,与合作伙伴共享商 ...
- LangChain结合LLM做私有化文档搜索
我们知道LLM(大语言模型)的底模是基于已经过期的公开数据训练出来的,对于新的知识或者私有化的数据LLM一般无法作答,此时LLM会出现"幻觉".针对"幻觉"问题 ...
- Windows CSC提权漏洞复现(CVE-2024-26229)
漏洞信息 Windows CSC服务特权提升漏洞. 当程序向缓冲区写入的数据超出其处理能力时,就会发生基于堆的缓冲区溢出,从而导致多余的数据溢出到相邻的内存区域.这种溢出会损坏内存,并可能使攻击者能够 ...
- 06-Python类与对象
什么是类 百度百科: 类是对象的抽象,对象是对客观事物的抽象. 用通俗的话来说: 类是类别的意思,是数据类型. 对象是类别下的具体事物. 也就是说: 类是数据类型,对象是变量. 比如: 自定义一种数据 ...
- 20-Docker镜像制作
查看镜像构建的历史 docker image history 26a5 #查看镜像26a5的构建历史 使用commit命令构建镜像 使用commit命令可以将容器构建成镜像. 将容器webserver ...
- MySQL自定义函数(User Define Function)开发实例——发送TCP/UDP消息
开发背景 当数据库中某个字段的值改为特定值时,实时发送消息通知到其他系统. 实现思路 监控数据库中特定字段值的变化可以用数据库触发器实现.还需要实现一个自定义的函数,接收一个字符串参数,然后将这个字符 ...
- 高通mm-camera平台 Camera bring up基本调试思路
原文:https://www.cnblogs.com/thjfk/p/4086001.html 确定硬件 1.首先对照原理图,检查camera module的pin脚连接是否正确. 2.用示波器量Ca ...