牛客小白月赛106 题解 更新至 F 题

news/2024/12/18 19:48:08/文章来源:https://www.cnblogs.com/advisedy/p/18615750

Preface

期末周闲的没事写一场小白月赛

我会在代码一些有必要的地方加上注释,签到题可能一般就不会写了.

以下是代码火车头:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <unordered_map>
#include <iomanip>
#define endl '\n'
#define int long long
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define rep2(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;template<typename T>
void cc(const vector<T> &tem) {for (const auto &x: tem) cout << x << ' ';cout << endl;
}template<typename T>
void cc(const T &a) { cout << a << endl; }template<typename T1, typename T2>
void cc(const T1 &a, const T2 &b) { cout << a << ' ' << b << endl; }template<typename T1, typename T2, typename T3>
void cc(const T1 &a, const T2 &b, const T3 &c) { cout << a << ' ' << b << ' ' << c << endl; }void cc(const string &s) { cout << s << endl; }void fileRead() {
#ifdef LOCALLfreopen("D:\\AADVISE\\Clioncode\\untitled2\\in.txt", "r", stdin);freopen("D:\\AADVISE\\Clioncode\\untitled2\\out.txt", "w", stdout);
#endif
}void kuaidu() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); }inline int max(int a, int b) {if (a < b) return b;return a;
}inline double max(double a, double b) {if (a < b) return b;return a;
}inline int min(int a, int b) {if (a < b) return a;return b;
}inline double min(double a, double b) {if (a < b) return a;return b;
}void cmax(int &a, const int &b) { if (b > a) a = b; }
void cmin(int &a, const int &b) { if (b < a) a = b; }
void cmin(double &a, const double &b) { if (b < a) a = b; }
void cmax(double &a, const double &b) { if (b > a) a = b; }
using PII = pair<int, int>;
using i128 = __int128;
using vec_int = std::vector<int>;
using vec_char = std::vector<char>;
using vec_double = std::vector<double>;
using vec_int2 = std::vector<std::vector<int> >;
using que_int = std::queue<int>;

Problem A. 最后DISCO

签到题还\(WA\)了一发。。。

明显要根据奇偶性直接判断出来就好了,一个小小的分类讨论。

但是需要注意\(b=1\)的情况。

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;//--------------------------------------------------------------------------------
//struct or namespace://--------------------------------------------------------------------------------signed main() {fileRead();kuaidu();T = 1;//cin >> T;while (T--) {int a, b, c, d;cin >> a >> b >> c >> d;if (b == 0) {if ((c+d)%2==1) cc("YES");else cc("NO");continue;}if (a % 2 == 0 or c % 2 == 0) {if (d % 2 == 0) cc("NO");else cc("YES");}else {if (d % 2 == 0) cc("YES");else cc("NO");}}return 0;
}/**/

Problem B. 末日DISCO

题目有一点点的意思,其实会发现我们构造一个

\[1,2,3,4 \\ 2,5,6,7 \\ 3,6,8,9\\ 4,7,9,10\\\]

这样一个对角线对称的矩阵就好了。

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;
int A[510][510];
//--------------------------------------------------------------------------------
//struct or namespace://--------------------------------------------------------------------------------signed main() {fileRead();kuaidu();T = 1;//cin >> T;while (T--) {cin >> n;int cnt = 0;rep(i, 1, n) {A[i][i] = ++cnt;rep(j, i+1, n) A[i][j] = A[j][i] = ++cnt;}rep(i, 1, n) {rep(j, 1, n) {cout << A[i][j] << " ";}cout << endl;}}return 0;
}/**/

Problem C. 明日DISCO

我们先想一个简单的,如果操作\(1\)的时候:

那么显然我们应该从棋盘的最大值开始,逐渐减少,直到不能减少为止。

所以操作\(2\)对应的就是从最小值开始,逐渐增大,直到不能增大为止。

一个简单的模拟,但是有一点要注意的就是我们在减少的时候可以直接将当前的权值\(val\)变成上下左右四个点中的最值

时间复杂度不会太大,因为可以感性的想到,如果有相邻的情况(正负性一致),那么就一定会不行。

代码写复杂了,刚刚写题解的时候才想到相邻的不行,\(v\)的时候直接暴力模拟去了。。。

//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;
int A[510][510];
//--------------------------------------------------------------------------------
//struct or namespace:
struct node {int x;int y;int val;
};//--------------------------------------------------------------------------------signed main() {fileRead();kuaidu();T = 1;//cin >> T;while (T--) {cin >> n;// vector<node> tem;rep(i, 1, n)rep(j, 1, n) {int a;cin >> a;A[i][j] = a;// tem.push_back({i, j, a});}auto cmp1 = [&](const node &q1, const node &q2) {return q1.val > q2.val;};auto cmp2 = [&](const node &q1, const node &q2) {return q1.val < q2.val;};priority_queue<node, vector<node>, decltype(cmp2)> F(cmp2);// for (auto &x: tem) F.push(x);rep(i, 1, n)rep(j, 1, n) F.push({i, j, A[i][j]});while (!F.empty()) {auto [x,y,val] = F.top();F.pop();if (A[x - 1][y] < val and A[x][y - 1] < val and A[x + 1][y] < val and A[x][y + 1] < val) {A[x][y] = max({A[x - 1][y], A[x][y - 1], A[x + 1][y], A[x][y + 1]});F.push({x, y, A[x][y]});}else {break;}}priority_queue<node, vector<node>, decltype(cmp1)> G(cmp1);rep(i, 1, n)rep(j, 1, n) G.push({i, j, A[i][j]});while (!G.empty()) {auto [x,y,val] = G.top();G.pop();// cc(x, y, val);if (A[x - 1][y] > val and A[x][y - 1] > val and A[x + 1][y] > val and A[x][y + 1] > val) {A[x][y] = min({A[x - 1][y], A[x][y - 1], A[x + 1][y], A[x][y + 1]});G.push({x, y, A[x][y]});}else {break;}}bool fl = 1;rep(i, 1, n) {rep(j, 1, n) {if (A[i][j] != 0) fl = 0;// cout << A[i][j] << " ";}// cout << endl;}if (fl) cc("YES");else cc("NO");}return 0;
}/**/

Problem D. 太阳系DISCO

一眼暴力,但是有一个技能操作。感性的想到,这个技能的操作由于是直接跳到对面,所以应该最多只会执行\(1\)次,那么就直接先不考虑这个暴力走一遍之后判断到达对面点的情况取个\(min\)就好了。代码写起来比\(C\)简单不少\((bushi\)

//--------------------------------------------------------------------------------
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;
int dp[N];
bool vis[N];
int st, ed, shun, ni, k;
//--------------------------------------------------------------------------------
//struct or namespace://--------------------------------------------------------------------------------signed main() {fileRead();kuaidu();T = 1;//cin >> T;while (T--) {cin >> n >> k >> st >> ed >> shun >> ni;st -= 1, ed -= 1;rep(i, 0, n-1) dp[i] = INF;queue<PII> F;F.push({st, 0});while (!F.empty()) {auto [x,val] = F.front();F.pop();if (vis[x]) continue;vis[x] = 1;dp[x] = val;F.push({(x + shun) % n, val + 1});F.push({(x - ni + n) % n, val + 1});}int ans = dp[ed];if (k > 0) cmin(ans, dp[(ed + n / 2) % n] + 1);if (ans >= INF / 2)ans = -1;cc(ans);}return 0;
}/**/

Problem E. 普通DISCO-1

可以想到我们每次的操作都是在一个\(lca\)的子树里面选择的,然后我们每次选择的时候如果是希望向下深度最大的话,那么肯定是向下深度第二的加到向下深度第一的上面,那么我们只需要枚举\(lca\),然后将最大值和次大值加起来取\(max\)就好了。、

记得特殊处理一下如果当前的点\(i\)如果只有一个子树的情况。因为这个\(wa\)了两发。。。

//--------------------------------------------------------------------------------
const int N = 5e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;
// int ans = INF;
//--------------------------------------------------------------------------------
//struct or namespace:
namespace z {vector<PII> A[N];int son[N], dep[N], dis[N], dis2[N];void dfs(const int x, const int pa) {son[x] = 1;dep[x] = dep[pa] + 1;for (auto &[y, val]: A[x]) {if (y == pa) continue;dfs(y, x);son[x] += son[y];if (dis[y] + 1 > dis[x]) dis2[x] = dis[x], dis[x] = dis[y] + 1;else if (dis[y] + 1 > dis2[x]) dis2[x] = dis[y] + 1;}}void clear(int n) {rep(i, 1, n) {A[i].clear();}}void add(int x, int y, int c = 1) { A[x].push_back({y, c}); }
}//--------------------------------------------------------------------------------signed main() {fileRead();kuaidu();T = 1;//cin >> T;while (T--) {cin >> n;z::clear(n);rep(i, 1, n-1) {int a, b;cin >> a >> b;z::add(a, b);z::add(b, a);}z::dfs(1, 0);int ans = 0;using namespace z;rep(i, 1, n) {cmax(ans, dep[i] + dis[i]);if (dis2[i] == 0) {continue;}cmax(ans, dis[i] + dis2[i] + dep[i] - 1);// cc(i, dis[i], dis2[i]);}cc(ans);}return 0;
}/**/

Problem F. 普通DISCO-2

首先一眼二分,求所有点深度的最大值的最小值。

然后考虑怎么处理,首先可以想到要将深度\(mid\)以下的求一个\(lca\),挪动的时候直接挪动\(lca\)这个点。

然后直接暴力枚举每个点和他交换之后满不满足就好了。

判断满不满足的时候我们就和\(E\)一样求一个向下深度的最大值就好了。

打了两场,感觉小白的\(F\)题貌似是铜--的难度?

//--------------------------------------------------------------------------------
const int N = 5e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1e16;
int n, m, T;//--------------------------------------------------------------------------------
//struct or namespace:
namespace z {vector<PII> A[N];int son[N], dep[N], fa[N], dis[N];//重儿子,顶根,时间戳,子树最右端时间戳,时间戳会对应节点xint hea[N], up[N], dnf[N], dnff[N], seq[N];int len[N];int tot;void dfs(int x, int pa) {son[x] = 1, dep[x] = dep[pa] + 1, fa[x] = pa;int t = 0;for (auto [y, val]: A[x]) {if (y == pa) continue;dis[y] = dis[x] + val;dfs(y, x);cmax(len[x], len[y] + 1);son[x] += son[y];if (!t or son[t] < son[y]) t = y;}hea[x] = t;}void dfs2(int x, int pa, int ding) {dnf[x] = ++tot, up[x] = ding, seq[dnf[x]] = x;if (hea[x]) dfs2(hea[x], x, ding);for (auto [y, val]: A[x]) {if (y == pa || y == hea[x]) continue;dfs2(y, x, y);}dnff[x] = tot;}void clear(int n) {tot = 0;rep(i, 1, n) {A[i].clear();dis[i] = hea[i] = up[i] = dnf[i] = seq[i] = 0;}}void add(int x, int y, int c = 1) {A[x].push_back({y, c});A[y].push_back({x, c});}int lca(int x, int y) {while (up[x] != up[y]) {if (dep[up[x]] < dep[up[y]]) swap(x, y);x = fa[up[x]];}if (dep[x] > dep[y]) swap(x, y);return x;}//返回x向上k次的点int upup(int x, int k) {if (dep[x] <= k) return -1;int to = dep[x] - k;while (dep[up[x]] > to) x = fa[up[x]];return seq[dnf[x] - (dep[x] - to)];}int dist(int x, int y) { return dis[x] + dis[y] - dis[lca(x, y)] * 2; }void work(int rt = 1) { dfs(rt, 0), dfs2(rt, 0, rt); }//x的子树里有y就返回1bool isFa(int x, int y) { return (dnf[x] <= dnf[y] and dnff[x] > dnf[y]); }
};//--------------------------------------------------------------------------------bool check(int mid) {using namespace z;int t = 0;rep(i, 1, n) {if (dep[i] < mid) continue;if (len[i] == 0) continue;if (t == 0) t = i;if (isFa(t, i)) continue;t = lca(t, i);}if (t == 0) return 1;if (len[1] + 1 <= mid) return 1;rep(i, 1, n) {if (isFa(t, i) or isFa(i, t)) continue;if (dep[i] >= mid) continue;if (dep[t] + len[i] <= mid and dep[i] + len[t] <= mid) return 1;}return 0;
}signed main() {fileRead();kuaidu();T = 1;//cin >> T;while (T--) {cin >> n;z::clear(n);rep(i, 1, n-1) {int a, b;cin >> a >> b;z::add(a, b);}z::work();int l = 0, r = n + 1;while (l + 1 != r) {int mid = l + r >> 1;if (check(mid)) r = mid;else l = mid;}cc(r);}return 0;
}/**/

PostScript

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/854993.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024-12-18 17 55 记录 Cambly trip`s summary and wher 1607b517085581159d14fe7750337be7

2024-12-18 17:55 记录 Cambly trip`s summary and where is the next ?https://tingwu.aliyun.com/doc/transcripts/g2y8qevxaayxnbeo?sl=1# 《2024-12-18 17:55 记录 Cambly trip`s summary and where is the next ?》1. 全文摘要 对话讲述了一个人通过使用美好的旅行来…

实验六 模板类、文件I/O和异常处理

1、实验任务一 Complex.hpp#pragma once#include <iostream> #include <stdexcept>// 声明 //////////////////////////////////////////////////// // 复数模板类声明 template<typename T> class Complex { public:Complex(T r = 0, T i = 0);Complex(cons…

免费设计Logo的新神器Slea.ai

使用Slea.ai,你可以在几分钟内设计出专业、高质量的Logo,支持多种场景应用,免费下载,实现自定义设计。品牌打造从未如此轻松!作为一名注重品牌形象的创作者或企业主,你是否苦于设计一款专业又独特的Logo?今天我要向大家推荐一个超级实用的网站——Slea.ai,它是一款免费的…

MOS管的寄生电容

我们经常看到,在电源电路中,功率MOS管的G极经常会串联一个小电阻,几欧姆到几十欧姆不等,那么这个电阻用什么作用呢? 这个电阻的作用有2个作用:限制G极电流,抑制振荡。 限制G极电流MOS管是由电压驱动的,是以G级电流很小,但是因为寄生电容的存在,在MOS管打开或关闭的时…

配置CentOS 7阿里yum源

备份yum源配置文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bakvi /etc/yum.repos.d/CentOS-Base.repo# CentOS-Base.repo # # The mirror system uses the connecting IP address of the client and the # update status of each mirror to …

源码信息收集

引子:上一篇主要介绍了与Web架构相关的信息收集,而在Web架构中有一至关重要的一环,那就是源码。Web应用中美观的ui、特色的功能全靠源码来实现,但同样的,几乎绝大多数与Web相关的漏洞都也都与其源码有关。而本篇则介绍几种常见的源码信息收集方式。附:完整笔记目录~ ps:…

标定和定位的关系

手眼标定手眼标定可以利用某真值位置和传感器观测位置对比得到外参。 关联本质上是外参不同引起的看同一外接参照物,认为自身运动轨迹的不同。位置如上观测同一建筑(三角形,上顶点是北方),真实轨迹(左图):是向北直行是在向正前方走世界坐标系->偏置传感器轨迹(中间图…

12.13

实验2 熟悉常用的HDFS操作1.实验目的 (1)理解HDFS在Hadoop体系结构中的角色; (2)熟练使用HDFS操作常用的Shell命令; (3)熟悉HDFS操作常用的Java API。 2. 实验平台 (1)操作系统:Linux(建议Ubuntu16.04或Ubuntu18.04); (2)Hadoop版本:3.1.3; (3)JDK版本:1.…

12.10

实验八:随机森林算法实现与测试一、实验目的 深入理解随机森林的算法原理,进而理解集成学习的意义,能够使用 Python 语言实现随机森林算法的训练与测试,并且使用五折交叉验证算法进行模型训练与评估。 二、实验内容 (1)从 scikit-learn 库中加载 iris 数据集,使用留出法…

Tengine:Nginx二次开发-高性能进化

前言:在当今的互联网时代,Web 服务器的性能和稳定性对于网站的成功至关重要。Nginx 以其高性能和可扩展性而闻名,但有时候,我们需要更多的特性来满足特定的业务需求。Tengine,作为一个由淘宝网发起的 Nginx 二次开发版本,不仅继承了 Nginx 的所有特性,还添加了许多高级功…