牛客周赛 Round 66(A—G)(并查集,线段树,思维,数位dp)

news2024/11/5 7:42:56

比赛链接

牛客周赛 Round 66

A题

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int N = 2e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int x, y, z;
void solve()
{
	cin >> x >> y >> z;
	cout << max(x + y + z - max({x, y, z}), max({x, y, z})) << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	// cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

B题

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int N = 2e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n;
void solve()
{
	cin >> n;
	for (int i = n; i >= 1; i--)
	{
		cout << i << " ";
	}
	cout << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

C题

思路

用指针模拟循环移动字符串即可。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int N = 2e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
string s;
void solve()
{
	cin >> s;
	int ans = 0;
	for (int i = s.size() - 1, j = 1; i >= 0; i--, j *= 10)
	{
		ans += (s[i] - '0') * j;
	}
	int len = s.size();
	for (int i = 1; i < s.size(); i++)
	{
		int sum = 0;
		for (int cnt = 1, j = i; cnt <= s.size(); cnt++, j++)
		{
			j = j % len;
			sum = sum * 10 + (s[j] - '0');
		}
		ans = min(ans, sum);
	}
	cout << ans << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

D题

思路

数据范围很小,只用一个并查集来维护所有的联通块,然后区间修改时直接暴力枚举。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
typedef pair<int, int> pii;
const int N = 2e3 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;

int n, m;
int sum[N];
double a[N];
struct DSU {
	std::vector<int> f, siz;

	DSU() {}
	DSU(int n) {
		init(n);
	}

	void init(int n) {
		f.resize(n);
		std::iota(f.begin(), f.end(), 0);
		siz.assign(n, 1);
	}

	int find(int x) {
		while (x != f[x]) {
			x = f[x] = f[f[x]];
		}
		return x;
	}

	bool same(int x, int y) {
		return find(x) == find(y);
	}

	bool merge(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) {
			return false;
		}
		siz[x] += siz[y];
		f[y] = x;
		return true;
	}

	int size(int x) {
		return siz[find(x)];
	}
};
void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> sum[i];
		a[i] = sum[i];
		sum[i] += sum[i - 1];
	}
	DSU dsu(n + 1);
	while (m--)
	{
		int op, l, r;
		cin >> op >> l;
		if (op == 1)
		{
			cin >> r;
			while (l > 1)
			{
				if (dsu.same(l - 1, l)) l--;
				else break;
			}
			while (r < n)
			{
				if (dsu.same(r, r + 1)) r++;
				else break;
			}
			double res = sum[r] - sum[l - 1];
			double val = res / (r - l + 1);
			for (int i = l; i <= r; i++)
			{
				a[i] = val;
			}
			for (int i = l + 1; i <= r; i++)
			{
				dsu.merge(i, i - 1);
			}
		}
		else
		{
			cout << fixed << setprecision(10) << a[l] << endl;
		}
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	// cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

E题

思路

我们用两个并查集分别维护其左边的祖先和右边的祖先,然后用线段树来维护区间赋值操作即可。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
typedef pair<int, int> pii;
const int N = 2e5 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;

int n, m;
int sum[N];
double a[N];
struct DSU {
	std::vector<int> f, siz;

	DSU() {}
	DSU(int n) {
		init(n);
	}

	void init(int n) {
		f.resize(n);
		std::iota(f.begin(), f.end(), 0);
		siz.assign(n, 1);
	}

	int find(int x) {
		while (x != f[x]) {
			x = f[x] = f[f[x]];
		}
		return x;
	}

	bool same(int x, int y) {
		return find(x) == find(y);
	}

	bool merge(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) {
			return false;
		}
		siz[x] += siz[y];
		f[y] = x;
		return true;
	}

	int size(int x) {
		return siz[find(x)];
	}
};
struct segmenttree
{
	struct node
	{
		int l, r;
		double maxx, tag;
	};
	vector<node>tree;

	segmenttree(): tree(1) {}
	segmenttree(int n): tree(n * 4 + 1) {}

	void pushup(int u)
	{
		auto &root = tree[u], &left = tree[u << 1], &right = tree[u << 1 | 1];
		root.maxx = max(left.maxx, right.maxx);
	}

	void pushdown(int u)
	{
		auto &root = tree[u], &left = tree[u << 1], &right = tree[u << 1 | 1];
		if (root.tag != 0)
		{
			left.tag = root.tag;
			right.tag = root.tag;
			left.maxx = root.maxx;
			right.maxx = root.maxx;
			root.tag = 0;
		}
	}

	void build(int u, int l, int r)
	{
		auto &root = tree[u];
		root = {l, r};
		if (l == r)
		{
			root.maxx = a[r];
		}
		else
		{
			int mid = l + r >> 1;
			build(u << 1, l, mid);
			build(u << 1 | 1, mid + 1, r);
			pushup(u);
		}
	}

	void modify(int u, int l, int r, double val)
	{
		auto &root = tree[u];
		if (root.l >= l && root.r <= r)
		{
			root.maxx = val;
			root.tag = val;
			return;
		}
		pushdown(u);
		int mid = root.l + root.r >> 1;
		if (l <= mid) modify(u << 1, l, r, val);
		if (r > mid) modify(u << 1 | 1, l, r, val);
		pushup(u);
	}

	double query(int u, int l, int r)
	{
		auto &root = tree[u];
		if (root.l >= l && root.r <= r)
		{
			return root.maxx;
		}
		pushdown(u);
		int mid = root.l + root.r >> 1;
		double res = -inf;
		if (l <= mid) res = query(u << 1, l, r);
		if (r > mid) res = max(res, query(u << 1 | 1, l, r));
		return res;
	}
};
void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> sum[i];
		a[i] = sum[i];
		sum[i] += sum[i - 1];
	}
	DSU dsuL(n + 1), dsuR(n + 1);
	segmenttree smt(n);
	smt.build(1, 1, n);
	while (m--)
	{
		int op, l, r;
		cin >> op >> l;
		if (op == 1)
		{
			cin >> r;
			l = dsuL.find(l);
			r = dsuR.find(r);
			double res = sum[r] - sum[l - 1];
			double val = res / (r - l + 1);
			smt.modify(1, l, r, val);
			int low = dsuR.find(l);
			int high = dsuL.find(r);
			if (low < high)
			{
				for (int i = low + 1; i <= high; i++)
				{
					dsuL.merge(i - 1, i);
				}
				for (int i = high - 1; i >= low; i--)
				{
					dsuR.merge(i + 1, i);
				}
			}
		}
		else
		{
			cout << fixed << setprecision(10) << smt.query(1, l, l) << endl;
		}
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	// cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

F题

思路

假设我们选中第 i i i个字符和第 j j j个字符( i < j i < j i<j)。想要比较 M o v e ( i ) Move(i) Move(i) M o v e ( j ) Move(j) Move(j)的大小,首先要看 s [ i ] s[i] s[i] s [ j ] s[j] s[j]的大小,如果相同,则需要继续比较 s [ i + 1 , j ] s[i+1,j] s[i+1,j] s [ i , j − 1 ] s[i,j-1] s[i,j1]的字典序大小。

因此我们可以预处理出一个 N x t N o t E q u a l NxtNotEqual NxtNotEqual数组, N x t N o t E q u a l [ i ] NxtNotEqual[i] NxtNotEqual[i]表示从 i i i开始,最小的 j j j j ≥ i j \ge i ji), s [ j ] s[j] s[j] s [ j + 1 ] s[j+1] s[j+1]不相同。

对于 i i i j j j,如果 N x t N o t E q u a l [ i ] ≥ j NxtNotEqual[i] \ge j NxtNotEqual[i]j则表示这段完全相同,否则比较 N x t N o t E q u a l [ i ] NxtNotEqual[i] NxtNotEqual[i] N x t N o t E q u a l [ i ] + 1 NxtNotEqual[i] +1 NxtNotEqual[i]+1的大小即可。

我们可以使用 s o r t sort sort函数,将上面的比较方式封装成一个lambda函数直接排序即可。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
typedef pair<int, int> pii;
const int N = 1e6 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;

int n, k;
int NxtNotEqual[N];
string s;
void solve()
{
	cin >> n >> k >> s;
	NxtNotEqual[n - 1] = n - 1;
	for (int i = n - 2; i >= 0; i--)
	{
		NxtNotEqual[i] = NxtNotEqual[i + 1];
		if (s[i] != s[i + 1])
			NxtNotEqual[i] = i;
	}
	vector<int>v(n, 0);
	iota(v.begin(), v.end(), 0);
	sort(v.begin(), v.end(), [&](int x, int y) {
		if (s[x] != s[y])
		{
			return s[x] < s[y];
		}
		if (x < y)
		{
			if (NxtNotEqual[x] >= y) return true;
			return s[NxtNotEqual[x] + 1] < s[NxtNotEqual[x]];
		}
		else
		{
			if (NxtNotEqual[y] >= x) return true;
			return s[NxtNotEqual[y]] < s[NxtNotEqual[y] + 1];
		}
	});
	int idx = v[k - 1];
	cout << s[idx];
	for (int i = 0; i < n; i++)
	{
		if (i == idx) continue;
		cout << s[i];
	}
	cout << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

G题

思路

mex的取值为 [ 0 , 10 ] [0,10] [0,10],因此我们可以从大到小枚举mex,找到满足条件的mex。

根据题意,我们需要在 [ x , x + k ] [x,x+k] [x,x+k]中寻找满足条件的数字,因此我们考虑使用数位dp。

我们定义, d p [ p ] [ s t ] dp[p][st] dp[p][st],从高位起第 1 1 1位到第 p p p位,拥有的数字用 s t st st这个集合表示,会有 d p [ p ] [ s t ] dp[p][st] dp[p][st]个数字的mex是当前枚举的mex。

代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
typedef pair<int, int> pii;
const int N = 10 + 5, M = 1e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f3f3f3f3f;
int x, k;
int a[N], dp[N][(1ll << 10) + 5];
int dfs(int p, int limit, int lead, int st, int m)
{//p表示数字的位数。limit表示可以填数的限制,无限制的话0-9随便填。lead表示有无前导0,st表示状态的二进制数(0-1024)。
	if (!p)
	{
		int mex = 0;
		while (st >> mex & 1)
		{
			mex++;
		}
		return mex == m;
	}

	if (!limit && !lead && dp[p][st] != -1)
		return dp[p][st];

	int ans = 0;
	int mx = limit ? a[p] : 9;//能枚举的数的上限

	for (int i = 0; i <= mx; i++)
	{
		if (lead && i == 0)
		{
			ans += dfs(p - 1, limit && i == mx, lead && i == 0, st, m);
		}
		else
		{
			ans += dfs(p - 1, limit && i == mx, lead && i == 0, st | (1ll << i), m);
		}
	}
	if (!limit && !lead)
	{
		dp[p][st] = ans;
	}
	return ans;
}
int calc(int x, int m)
{
	int p = 0;
	do
	{
		a[++p] = x % 10;
		x /= 10;
	} while (x);
	memset(dp, -1, sizeof(dp));
	return dfs(p, 1, 1, 0, m);
}
void solve()
{
	cin >> x >> k;
	int l = x, r = x + k;
	for (int i = 10; i >= 0; i--)
	{
		int ans = calc(r, i) - calc(l - 1, i);
		if (ans)
		{
			cout << i << " " << ans << endl;
			return;
		}
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker部署Portainer CE结合内网穿透实现容器的可视化管理与远程访问

文章目录 前言1. 本地安装Docker2. 本地部署Portainer CE3. 公网远程访问本地Portainer-CE3.1 内网穿透工具安装3.2 创建远程连接公网地址4. 固定Portainer CE公网地址前言 本篇文章介绍如何在Ubuntu中使用docker本地部署Portainer CE可视化管理工具,并结合cpolar实现公网远程…

数据结构之二叉树--前序,中序,后序详解(含源码)

二叉树 二叉树不能轻易用断言&#xff0c;因为树一定有空 二叉树链式结构的实现 在学习二叉树的基本操作前&#xff0c;需先要创建一棵二叉树&#xff0c;然后才能学习其相关的基本操作。 typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType _data;struct B…

数据库条件查询排查——引号故障

一、错误代码 $where_查询职汇总员[$value头[EmpCode]]$value职员[EmpCode]; 二、正常写法 $where_查询职汇总员[EmpCode]$value职员[EmpCode]; 三、原因 前一个是变量嵌套&#xff0c;这里不需要嵌套

前端用docker部署

1、环境检查 首先需要确认服务器上是否已经安装docker了。 在服务器上执行docker -v 显示对应的版本号说明已经安装好了docker 2、部署 使用Docker部署若依项目的前端服务&#xff0c;我们最终实现的是&#xff1a;启动一个镜像&#xff0c;我们的整个前端就启动了&#xf…

Matlab实现白鲸优化算法(BWO)求解路径规划问题

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1内容介绍 白鲸优化算法&#xff08;BWO&#xff09;是一种受自然界白鲸捕食行为启发的新型优化算法&#xff0c;它通过模拟白鲸的群体捕猎策略和社会互动来探索问题的最优解。BWO因其强大的全局搜索能力和高效的局部搜索能…

CPU 中央处理器调优

文章目录 1.1 CPU处理方式&#xff1a;1.2 查看CPU一秒钟有多个切换多少次。1.3 调整进程优先级使用更多CPU1.4 CPU亲和力1.5 CPU 性能监控1.6 CPU 利用率比例分配&#xff1a; 1.1 CPU处理方式&#xff1a; 批处理&#xff0c;顺序处理请求。(切换次数少&#xff0c;吞吐量大…

C#:强大而优雅的编程语言

在当今的软件开发领域&#xff0c;C#作为一种广泛应用的编程语言&#xff0c;以其强大的功能、优雅的语法和丰富的生态系统&#xff0c;受到了众多开发者的喜爱。本文将深入探讨 C#的各个方面&#xff0c;展示它的魅力和优势。 一、C#的历史与发展 C#是由微软公司开发的一种面…

信息安全工程师(74)网络安全风险评估技术方法与工具

前言 网络安全风险评估是依据有关信息安全技术和管理标准&#xff0c;对网络系统的保密性、完整性、可控性等安全数据进行科学评价的过程。 一、网络安全风险评估技术方法 风险评估程序 资产评估&#xff1a;确定需要保护的资源。威胁评估&#xff1a;确定可能对资产造成危害的…

【InfluxDB】InfluxDB 2.x基础概念及原理

InfluxDB简介 什么是时序数据库 时序数据库&#xff0c;全称时间序列数据库&#xff08;Time Series Database&#xff0c;TSDB&#xff09;&#xff0c;用于存储大量基于时间的数据。时序数据库支持时序数据的快速写入、持久化&#xff0c;多维度查询、聚合等操作&#xff0…

sparkSQL面试题

一、查询所有数学课程成绩大于语文课程成绩的学生学号 数据 1,yuwen,43 1,shuxue,55 2,yuwen,77 2,shuxue,88 3,yuwen,98 3,shuxue,65 3,yingyu,88 基本步骤&#xff1a; 进行行转列比较语文与数学的成绩 SQL代码&#xff1a; with t1 as(SELECT id,sum(if(name yuwen,sc…

金融标准体系

目录 基本原则 标准体系结构图 标准明细表 金融标准体系下载地址 基本原则 需求引领、顶层设计。 坚持目标导向、问题导向、结果 导向有机统一&#xff0c;构建支撑适用、体系完善、科学合理的金融 标准体系。 全面系统、重点突出。 以金融业运用有效、保护有力、 管理高…

Spring Boot解决 406 错误之返回对象缺少Getter/Setter方法引发的问题

目录 前言1. 问题背景2. 问题分析2.1 检查返回对象 3. 解决方案3.1 确保Controller返回Result类型3.2 测试接口响应 4. 原理探讨5. 常见问题排查与优化建议结语 前言 在Spring Boot开发中&#xff0c;接口请求返回数据是系统交互的重要环节&#xff0c;尤其在开发RESTful风格的…

如何自学机器学习?

自学机器学习可以按照以下步骤进行&#xff1a; 一、基础知识准备 数学基础&#xff1a; 高等数学&#xff1a;学习微积分&#xff08;包括导数、微分、积分等&#xff09;、极限、级数等基本概念。这些知识是后续学习算法和优化方法的基础。 线性代数&#xff1a;掌握矩阵…

SQL,力扣题目1709,访问日期之间最大的空档期

一、力扣链接 LeetCode_1709 二、题目描述 表&#xff1a; UserVisits ------------------- | Column Name | Type | ------------------- | user_id | int | | visit_date | date | ------------------- 该表没有主键&#xff0c;它可能有重复的行 该表包含用户访问…

C# 日志框架 NLog、log4net 和 Serilog对比

文章目录 前言NLog、log4net 和 Serilog 三个框架的详细对比:一、NLog优点:缺点:二、 log4net优点缺点三、Serilog优点缺点四、Serilog使用举例总结前言 NLog、log4net 和 Serilog 三个框架的详细对比: NLog、log4net 和 Serilog 是三个非常流行的 .NET 日志框架,它们各自…

电路设计过程就是波形整形过程

这种说法有一定的道理。在电路设计中&#xff0c;常常需要对输入的电信号波形进行处理和调整&#xff0c;以满足后续电路或系统的要求&#xff0c;这在某种程度上可以理解为波形整形的过程。 例如&#xff0c;在数字电路中&#xff0c;输入的信号可能存在噪声、干扰或者不符合…

系统架构设计师(软考高级)一站式通关课程

系统架构设计师&#xff08;软考高级&#xff09; 一站式通关课程 系统架构设计师&#xff08;软考高级&#xff09;教程&#xff08;三连评论分享链接&#xff01;&#xff09; &#x1f3af; 课程亮点&#xff1a; 全面覆盖&#xff1a; 从基础概念到高级应用&#xff0c;涵盖…

源码阅读心得---如何从零开始阅读一个框架的源码

写在前头&#xff0c;菜鸟作者的一些碎碎念&#xff1a; 回想自己2022年研三第一次去实习的时候&#xff0c;是到了一个数据库小组&#xff0c;是一个做数据库内核的小组&#xff0c;leader分配的目标是先把read/write流程搞明白。第一次出校实习&#xff0c;一来就是直接读内核…

Java项目实战II基于Java+Spring Boot+MySQL的体育馆使用预约平台的设计与实现(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着全民健…