ABC346 A-G 题解

news2024/9/29 3:24:31

ABC346 A-G题解

  • A
    • 题目
    • AC Code:
    • 时间复杂度
  • B
    • 题目
    • 时间复杂度
    • AC Code:
  • C
    • 题目
    • 时间复杂度
    • AC Code:
  • D
    • 题目
    • 时间复杂度
    • AC Code:
  • E
    • 题目
    • 时间复杂度
    • AC Code:
  • F
    • 题目
    • 时间复杂度
    • AC Code:
  • G
    • 题目
    • 时间复杂度
    • AC Code:

下面的内容不包括题目翻译,要想获取题目翻译,请参照 这篇教程 来获取题目翻译。

A

题目

循环处理每一个数字即可,不再赘述。

AC Code:

#include <iostream>
using namespace std;
int n, a[200100];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i < n; i++) cout << a[i] * a[i + 1] << ' ';
	return 0;
}

时间复杂度

O ( N ) O(N) O(N)

B

题目

由于键盘是有规律的,所以任何子串都可以从从 12 12 12 以内开始的子串提取出来。暴力即可, 200 200 200 够用了。

时间复杂度

O ( 20 0 2 ) O(200^2) O(2002)

AC Code:

#include <iostream>
#include <cstring>
using namespace std;
int w, b;
string s = "wbwbwwbwbwbw";
string s1;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> w >> b;
	for (int i = 0; i <= 20; i++) {
		for (int j = 0; j < (int)s.length(); j++) {
			s1.push_back(s[j]);
		}
	}
	for (int i = 0; i < (int)s1.size(); i++) {
		int cntw = 0, cntb = 0;
		for (int j = i; j < (int)s1.size(); j++) {
			if (w == cntw && b == cntb) {
				cout << "Yes\n";
				return 0;
			}
			if (s1[j] == 'b') cntb++;
			else cntw++;
		}
	}
	cout << "No";
	return 0;
}

C

题目

我们发现,与其一个一个找没有出现在 A A A 里面的数,不如从小于等于 K K K 的所有数字里面寻找在 A A A 里出现过的数字。我们使用一个 map 记录这个数字有没有被去除。对于每一个 A i A_i Ai,如果 A i ≤ K A_i \le K AiK 且没有被去除,就从所有小于等于 K K K 的数字的和里面减去这个数字,把这个数字标记为已去除。

时间复杂度

O ( N log ⁡ ( 1 0 9 ) ) O(N\log(10^9)) O(Nlog(109))

AC Code:

#include <iostream>
#include <map>
using namespace std;
int n;
long long k, a[200100];
long long ans;
map<long long, bool> m;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> k;
	ans = (k + 1ll) * k / 2ll;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		if (!m[a[i]] && a[i] <= k) {
			ans -= a[i];
			m[a[i]] = 1;
		}
	}
	cout << ans;
	return 0;
}

D

题目

我们发现,一个好字串无非就是可以从某个位置切成两个字串,字串里相邻两个字符不一样,字串切开的位置的字符相同。

我们计算前缀后缀以 01 开始的相邻两个字符不一样的代价,即使这个字串变为 10101... 的代价。对于每一个分割点,如果原串长度是偶数,那么这两个分割后的字串另外一边要一样,否则,不一样。计算代价,取最小值即可。

时间复杂度

O ( N ) O(N) O(N)

AC Code:

#include <algorithm>
#include <iostream>
using namespace std;
int n;
char s[200100];
int c[200100];
long long sum[200100];
long long c00[200100], c01[200100], c10[200100], c11[200100];
long long ans = 1e18;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> s[i];
	for (int i = 1; i <= n; i++) cin >> c[i];
	for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + c[i];
	for (int i = 1; i <= n; i++) {
		c00[i] = c00[i - 1] + ((i - 1) % 2 == s[i] - '0') * c[i];
		c01[i] = c01[i - 1] + (i % 2 == s[i] - '0') * c[i];
	}
	for (int i = n; i >= 1; i--) {
		c10[i] = c10[i + 1] + ((n - i) % 2 == s[i] - '0') * c[i];
		c11[i] = c11[i + 1] + ((n - i + 1) % 2 == s[i] - '0') * c[i];
	}
	for (int i = 1; i < n; i++) {
		if (n % 2 == 0) {
			ans = min({ans, c00[i] + c10[i + 1], c01[i] + c11[i + 1]});
		}
		else {
			ans = min({ans, c01[i] + c10[i + 1], c00[i] + c11[i + 1]});
		}
	}
	cout << ans;
	return 0;
}

E

题目

我们倒着考虑所有操作,对于每一个横排操作,如果之前(指更晚的操作)把这一排覆盖了,那么跳过这个操作,否则统计没被覆盖的列数,该颜色数量加上这个值,把这一排标记为操作了,剩余横排数量减一,结束。
如果这是一个竖列操作,如果这一列没有被覆盖,该颜色数量加上没被覆盖的横排数,把这一列标记为被覆盖,没被覆盖的列数减去一,结束。

时间复杂度

O ( 1 ) O(1) O(1)

AC Code:

#include <iostream>
#define int long long
using namespace std;
int h, w;
int m;
int t[200100], a[200100], x[200100];
int c_h, c_w;
int cnt[200100];
int cnt1;
bool vis_h[200100], vis_w[200100];

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> h >> w;
	cin >> m;
	c_h = h, c_w = w;
	for (int i = m; i >= 1; i--) cin >> t[i] >> a[i] >> x[i];
	for (int i = 1; i <= m; i++) {
		if (t[i] == 1) {
			if (c_h && !vis_h[a[i]]) {
				c_h--;
				cnt[x[i]] += c_w;
				vis_h[a[i]] = 1;
			}
		}
		else {
			if (c_w && !vis_w[a[i]]) {
				c_w--;
				cnt[x[i]] += c_h;
				vis_w[a[i]] = 1;
			}
		}
	}
	cnt[0] += c_h * c_w;
	for (int i = 0; i <= 200000; i++) {
		if (cnt[i]) cnt1++;
	}
	cout << cnt1 << '\n';
	for (int i = 0; i <= 200000; i++) {
		if (cnt[i]) {
			cout << i << ' ' << cnt[i] << '\n';
		}
	}
	return 0;
}

F

题目

如果重复三次的情况可以,那么二次,一次的情况也可以。如果重复四次的情况不可以,重复五次,六次也不可以。可以看出这东西满足单调性,可以二分。

我们判断这个情况可不可以时,如果暴力在重复 N N N 次的串中寻找的话, N N N 很大,会爆炸。我们记录现在找到了重复第几遍的串中的第几个字符,分情况讨论找完后会不会跳到下一遍即可。如果跳不到下一遍,找到刚刚好重复我们要重复的次数的位置,否则,让总共要重复的次数除以这一边中字符个数就是要重复的次数,还要考虑这个坐标多的次数。

如果重复了 N + 1 N+1 N+1 边才找完或没找完,就说明不行。

细节很多,考验你的调试技术。

时间复杂度

O ( ∣ T ∣ log ⁡ ( N ∣ S ∣ ) ) O(|T|\log(N|S|)) O(Tlog(NS))

AC Code:

#include <iostream>
#define int long long

using namespace std;
int n;
string s, t;
int cnt[200100][50];
int idx[200100][50];
bool check(int x) {
	int now1 = 0, now2 = 0;
	for (int i = 0; i < (int)t.size(); i++) {
		if (!cnt[0][t[i] - 'a']) return 0;
		if (cnt[now2][t[i] - 'a'] >= x) {
			int tmp = x;
			if (now2) tmp += cnt[0][t[i] - 'a'] - cnt[now2][t[i] - 'a'];
			now2 = idx[tmp][t[i] - 'a'] + 1;
		}
		else {
			int tmp = x;
			tmp -= cnt[now2][t[i] - 'a'];
			now1++;
			now2 = 0;
			if (cnt[0][t[i] - 'a'] >= tmp) {
				now2 = idx[tmp][t[i] - 'a'] + 1;
			}
			else {
				now1 += tmp / cnt[0][t[i] - 'a'];
				now2 = idx[tmp % cnt[0][t[i] - 'a']][t[i] - 'a'] + 1;
				if (tmp % cnt[0][t[i] - 'a'] == 0) {
					now1--;
					now2 = idx[cnt[0][t[i] - 'a']][t[i] - 'a'];
				}
			}
		}
		now1 += now2 / (int)s.size();
		now2 %= (int)s.size();
		if (now1 > n || (now1 == n && now2)) return 0;
	}
	return 1;
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> s >> t;
	for (int i = (int)s.size() - 1; i >= 0; i--) {
		for (int j = 0; j < 26; j++) cnt[i][j] = cnt[i + 1][j];
		cnt[i][s[i] - 'a']++;
	}
	for (int i = (int)s.size() - 1; i >= 0; i--)
		for (int j = 0; j < 26; j++) idx[cnt[0][j] - cnt[i + 1][j]][j] = i;
	int l = 0, r = n * (int)s.size();
	while (l < r) {
		int mid = (l + r + 1) / 2;
		if (check(mid)) {
			l = mid;
		}
		else {
			r = mid - 1;
		}
	}
	cout << l;
	return 0;
}

G

题目

我们可以找到对于每一个 A i A_i Ai,它的上一个和它相同的值的位置和下一个和它相同的值的位置。通过正序和倒序便利数组,存储这个值上一个出现位置,每遇到一个值将其上一个和它相等的值的位置更新为我们储存的这个值的位置,在更新这个值的上一个出现位置为现在遍历到的位置。

这样就算出了对于每一个只出现一次的数的区间范围,拿样例解释:

1 2 1 4 3 3 3 2 2 4

如果以第三个元素:1 为只出现一次元素的话,区间可以这么取:

1 [2 {1] 4 3 3 3 2 2 4}

其中中括号是左端点的范围,大括号是右端点的取值范围。

这样就有 2 × 8 2\times 8 2×8 16 16 16 种情况。

但是就这样会有重复的区间,朴素去重就是 N 2 N^2 N2 的时间复杂度了,怎么办呢?

我们可以把一个区间表示成一个点: [ i , j ] [i,j] [i,j] 表示成 ( i , j ) (i,j) (i,j),如图 i , j i,j i,j 2 , 3 2,3 2,3

在这里插入图片描述

那么两个区间里的点的组合是不是就可以表示成一个矩形?

那么样例中例子的矩形就是:

( 2 , 3 ) to ( 3 , 10 ) (2,3) \text{to} (3,10) (2,3)to(3,10)

这个矩形的面积就是这个值只有一个的区间的总和。

那么把这些矩形的面积并起来,求这个不规则图形的总面积就是我们要求的答案?

你应该可以想到 扫描线。

时间复杂度

O ( N log ⁡ ( N ) ) O(N\log(N)) O(Nlog(N))

什么?你不会?我放的链接是拿来干嘛的?

AC Code:

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n, a[200100];
int l[200100], r[200100], l1[200100], r1[200100];
struct node{
	int l, r, tag;
	long long sum;
};
node t[1600100];
void maketree(int l, int r, int p) {
	t[p].l = l;
	t[p].r = r;
	if (l < r) {
		maketree(l, (l + r) / 2, p * 2);
		maketree((l + r) / 2 + 1, r, p * 2 + 1);
	}
}
void add(int l, int r, int p, int k) {
	if (t[p].l > r || t[p].r < l) return;
	if (l <= t[p].l && t[p].r <= r) {
		t[p].tag += k;
		if (t[p].tag) t[p].sum = t[p].r - t[p].l + 1;
		else t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
		return;
	}
	add(l, r, p * 2, k);
	add(l, r, p * 2 + 1, k);
	if (!t[p].tag) t[p].sum = t[p * 2].sum + t[p * 2 + 1].sum;
}
struct segment{
	int l, r, x, f;
};
segment seg[1600100];
int segcnt;
bool cmp(segment a, segment b) {
	if (a.x == b.x) return a.f < b.f;
	return a.x < b.x;
}
long long ans;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i <= n; i++) {
		l[i] = r1[a[i]];
		r1[a[i]] = i;
	}
	memset(l1, 0x3f, sizeof(l1));
	for (int i = n; i >= 1; i--) {
		r[i] = l1[a[i]];
		l1[a[i]] = i;
	}
	for (int i = 1; i <= n; i++) r[i] = min(r[i], n + 1);
	for (int i = 1; i <= n; i++) {
		segcnt++;
		seg[segcnt].l = i;
		seg[segcnt].r = r[i] - 1;
		seg[segcnt].x = l[i];
		seg[segcnt].f = 1;
		segcnt++;
		seg[segcnt].l = i;
		seg[segcnt].r = r[i] - 1;
		seg[segcnt].x = i;
		seg[segcnt].f = -1;
	}
	maketree(1, n, 1);
	sort(seg + 1, seg + segcnt + 1, cmp);
	for (int i = 1; i < segcnt; i++) {
		add(seg[i].l, seg[i].r, 1, seg[i].f);
		ans += (long long)(seg[i + 1].x - seg[i].x) * (long long)t[1].sum;
	}
	cout << ans;
	return 0;
}

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

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

相关文章

Leo赠书活动-21期 《一篇讲明白 Hadoop 生态的三大部件》

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

国产数据库中统计信息自动更新机制

数据库中统计信息描述的数据库中表和索引的大小数以及数据分布状况&#xff0c;统计信息的准确性对优化器选择执行计划时具有重要的参考意义。本文简要整理了下传统数据库和国产数据库中统计信息的自动更新机制&#xff0c;以加深了解。 1、数据库统计信息介绍 优化器是数据库…

文生图大模型Stable Diffusion的前世今生!

1、引言 跨模态大模型是指能够在不同感官模态(如视觉、语言、音频等)之间进行信息转换的大规模语言模型。当前图文跨模态大模型主要有&#xff1a; 文生图大模型&#xff1a;如 Stable Diffusion系列、DALL-E系列、Imagen等 图文匹配大模型&#xff1a;如CLIP、Chinese CLIP、…

Chrome 插件 tabs API 解析

Chrome.tabs API 解析 使用 chrome.tabs API 与浏览器的标签页系统进行交互&#xff0c;可以使用此 API 在浏览器中创建、修改和重新排列标签页 Tabs API 不仅提供操作和管理标签页的功能&#xff0c;还可以检测标签页的语言、截取屏幕截图&#xff0c;以及与标签页的内容脚本…

Linux基础命令大全

1、pwd&#xff1a;显示当前路径 cd &#xff1a;切换目录 用法&#xff1a;cd cd ../ 切换到上级目录 cd / 切换到根目录 cd ~ &#xff08;或只有cd &#xff09;切换到当前用户主目录(home底下以用户名命名的文件夹) /root目录mkdir 创建目录 mkdir 目录名 -p 递归创建目录…

短视频账号矩阵系统/开发 -- -- -- 路径积ai算法上线

短视频账号矩阵系统&#xff0c;短视频矩阵系统开发3年技术之路&#xff0c;目前已经在技术竞品出沉淀出来&#xff0c;近期技术迭代的新的功能同步喽&#xff1a; php7.4版本&#xff0c;自研框架&#xff0c;有开发文档&#xff0c;类laravel框架 近期剪辑迭代的技术算法&am…

RuoYi-Vue-Plus(permission.js 和 request.js 封装)

一、路由守卫 前端路径: src\permission.js 官网: 介绍 | Vue Router (vuejs.org)https://router.vuejs.org/zh/introduction.htmlpermission.js 通过 router.beforeEach 注册一个全局前置守卫 对登录流程进行控制有权限,则根据roles权限生成可访问的路由表无线权限则跳转登…

数据结构算法刷题笔记——题型解法

数据结构算法刷题笔记——题型解法 一、常用容器1.1 vector1.1.1 vector基本操作1.1.1.0 头文件#include<vector>1.1.1.1 构造一个vector容器1.1.1.2 元素访问1.1.1.3 元素个数 .size()1.1.1.4 最大容量 .capacity()1.1.1.5 改变容器有效元素个数 .resize(n)1.1.1.6 改变…

释放量子洪荒之力!详解NVIDIA 的 CUDA Q-wist

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨王珩 编译/排版丨沛贤 深度好文&#xff1a;1500字丨10分钟阅读 量子计算曾经只是一个局限于理论推测的领域&#xff0c;现在得益于 NVIDIA 的开拓性努力&#xff0c;正在转变为现实。…

react-navigation

Getting started | React Navigation

【绘图案例-自定义进度条 Objective-C语言】

一、好,我们接着来说这个自定义进度条 1.这个Slider啊,简单的这个value属性,介绍完了,以后,监听也可以监听的到了,接下来,我们来做这个自定义进度条啊, 那么,首先啊,我是这么想的,在这个slider的最小值、和、最大值、我给它改成0、到、1、 因为如果这样的话,到时候…

Mac系统中使用VSCode安装C#开发环境进行编译调试

VSCode安装插件 C#c# Dev Kit 安装Mac版本 .net .net下载地址 查看安装结果 dotnet --list-sdksdotnet --info配置环境变量 open -e ~/.bash_profile添加如下内容 export DOTNET_ROOT/usr/local/share/dotnet export PATH$PATH:$DOTNET_ROOT终端重新加载配置文件 sourc…

ArrayList和LinkedList有什么区别?

ArrayList和LinkedList的区别 ArrayList 和 LinkedList 是 Java 中常用的两种集合类&#xff0c;它们都实现了 List 接口&#xff0c;但在内部实现和性能上有一些区别。 内部实现&#xff1a; ArrayList 使用数组实现&#xff0c;它的元素在内存中是连续存储的&#xff0c;每…

【uniapp】uniapp实现免密登录

文章目录 一、概要二、整体架构流程三、技术名词解释四 、技术细节1.存取token有效期&#xff1f;2.使用setStorageSync而不使用setStorage&#xff1f;3.使用onLaunch而不使用全局路由&#xff1f; 一、概要 打开一个网页或小程序的时候&#xff0c;我们有时候会自动进入主页…

ExoPlayer架构详解与源码分析(12)——Cache

系列文章目录 ExoPlayer架构详解与源码分析&#xff08;1&#xff09;——前言 ExoPlayer架构详解与源码分析&#xff08;2&#xff09;——Player ExoPlayer架构详解与源码分析&#xff08;3&#xff09;——Timeline ExoPlayer架构详解与源码分析&#xff08;4&#xff09;—…

【XR806开发板试用】Ubuntu下烧写方法

烧写路径在工程目录下的device/xradio/xr806/xr_skylark/tools文件夹下&#xff0c;下载工具配置文件在 settings.ini 中 iBaud属性是波特率&#xff0c; strComDev属性是开发板连接电脑的usb口&#xff0c;通过 ls /dev/ttyUSB* 命令查询 之后在命令行输入 ./phoenixMC 开…

快速上手Pytrch爬虫之爬取某应图片壁纸

一、前置知识 1 爬虫简介 网络爬虫&#xff08;又被称作网络蜘蛛、网络机器人&#xff0c;在某些社区中也经常被称为网页追逐者)可以按照指定的规则&#xff08;网络爬虫的算法&#xff09;自动浏览或抓取网络中的信息。 1.1 Web网页存在方式 表层网页指的是不需要提交表单&…

二叉树|450.删除二叉搜索树中的节点

力扣题目链接 class Solution { public:TreeNode* deleteNode(TreeNode* root, int key) {if (root nullptr) return root; // 第一种情况&#xff1a;没找到删除的节点&#xff0c;遍历到空节点直接返回了if (root->val key) {// 第二种情况&#xff1a;左右孩子都为空&…

bugku-web-Flask_FileUpload

查看页面源码 这里提示给他一个文件&#xff0c;它将返回一个python运行结果给我&#xff0c;并且提示只能上传jpg和png文件 传递一个图片 查看源码 传递一个非图片 将源码写入新建的txt文件中 print(hello world) 将文件后缀改为jpg 上传 上传成功 查看源码 得到运行结果 我…

python实战之基础篇(一)

1. 注释 # coding utf-8 # 该注释放到文件第一行, 这个注释告诉python解释器该文件的编码集是UTF-82. 导入语句有三种形式 import <模块名> from <模块名> import <代码元素> from <模块名> import <代码元素> as <代码元素别名>3. 获取…