IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Codeforces Global Round 20 A~F1题解 -> 正文阅读

[数据结构与算法]Codeforces Global Round 20 A~F1题解

太困,实在撑不住,F2早上起来再补罢,抱歉了。


A. Log Chopping

题意:

给了一堆长度不一的木头,问能够剁几刀。

思路:

直接计算即可。

时间复杂度: O ( n ) O(n) On

int n;
signed main() {
	cf{
		sf(n);
		int res = 0;
		for (int i = 1, x; i <= n; i++)
			sf(x), res += x - 1;
 
		if (res & 1)
			puts("errorgorn");
		else
			puts("maomao90");
	}
	return 0;
}

B. I love AAAB

题意:

A B 、 A A B 、 A A A B … … AB、AAB、AAAB…… ABAABAAAB 按照任意顺序插入一个空字符串,能否得到所给字符串。

思路:

如果所给字符串能够被构造的话,一定会符合两种条件:

  • 最后一个字符为 B B B
  • 所有的前缀子串中,字符 A A A 的数量必定 ≥ \geq 字符 B B B 的数量。

时间复杂度: O ( n ) O(n) On

signed main() {
	cf{
		string res;
		cin >> res;
		bool st = true;
		int a = 0, b = 0;
		for (auto i : res)
			if (i == 'B') {
				b++;
				if (a < b) {
					st = false;
					break;
				}
			} else
				a++;

		if (res[res.size() - 1] == 'A')
			st = false;

		if (st)
			puts("YES");
		else
			puts("NO");
	}
	return 0;
}

C. Unequal Array

题意:

给定一个长度为 n n n 的数组 s s s,定义一种操作,将 s [ i ] , s [ i + 1 ] s[i],s[i+1] s[i]s[i+1] 的值改为任意一个值 x x x 1 ≤ i < n 1\leq i<n 1i<n

问最少进行多少次操作,使得 1 ≤ i < n 1\leq i<n 1i<n s [ i ] = = s [ i + 1 ] s[i]==s[i+1] s[i]==s[i+1] i i i 的个数 ≤ 1 \leq 1 1

思路:

这又是一道结论题。
找到相邻数相同的区间的最左和最右端点,我们想要做的就是将 [ l , r ] [l,r] [l,r] 这个区间中的相邻数相同的情况减为 1 1 1,那么操作次数就是 r ? l ? 2 r - l - 2 r?l?2
这里需要特判下原本就为零的情况与计算出的操作数为非正数的情况。

时间复杂度: O ( n ) O(n) On

int n;
int s[N];
signed main() {
	cf{
		sf(n);
		for (int i = 1; i <= n; i++)
			sf(s[i]);
 
		int tmp = 0, l = n + 1, r = 0;
		vector<int> ans;
		for (int i = 1; i < n; i++)
			if (s[i] == s[i + 1])
				l = min(l, i), r = max(r, i + 1);
 
		if (r - l <= 1)
			puts("0");
		else
			pfn(max(r - l - 2, 1ll));
	}
	return 0;
}

D. Cyclic Rotation

题意:

给定一个长度为 n n n 的数组 s s s,可以对其进行任意次数的以下操作:
选择两个下标 l 、 r , s [ l ] = = s [ r ] ( 1 ≤ l < r ≤ n ) l、r,s[l]==s[r](1\leq l<r\leq n) lrs[l]==s[r]1l<rn ,将区间内的数循环左移一步,即:
s [ l … … r ] = > s [ l + 1 , l + 1 , l + 3 … … r , l ] s[l……r] => s[l+1,l+1,l+3……r,l] s[lr]=>s[l+1,l+1,l+3r,l]
问是否可以通过任意次操作,将原数组转化为目标数组。

思路:

这道题感觉是模拟加一点点贪心。
具体代码讲解有些繁琐,这里就大致讲一下思路罢:

首先要确定一点,这两个数组的最后一个数必须相同,否则必然无法转化;
那么接下来就顺利成章的从后往前遍历,也就是模拟它循环左移的过程:
如果遍历到下标 i i i a [ i ] ≠ b [ i ] a[i]\neq b[i] a[i]?=b[i] ,我们需要判断前面是否还有 b [ i ] b[i] b[i] ,如果没有自然可以直接 f a l s e false false,有的话,就需要以 i i i 为右端点进行一次操作。
但是左端点呢?这里不能早早地定下左端点,需要贪心和下标最小的值为 b [ i ] b[i] b[i] 的位置 j j j 进行交换。如果该数组可以转化成功的话,如果 b [ j ] = = a [ j ] b[j]==a[j] b[j]==a[j] 自然是不用变换的,但是 b [ j ] ≠ a [ j ] b[j]\neq a[j] b[j]?=a[j] 的话,这里的 b [ j ] b[j] b[j] 必定是作为一个左端点与后面的点共同进行一次操作。

所以大致思路就是模拟这一过程,如果遍历到不相同的点时,它右边的点能够匹配、前面的相同值的下标足够进行匹配的话,那就直接进行一次操作;否则就判断它是否能够作为操作的左端点,能就重新判断下一个点,否则就直接 f a l s e false false

Ps.代码中我用 j j j 来表示遍历到该点时正在多少次操作之中。

人菜码多别骂了,佬们应该有更简便的解法

时间复杂度: O ( n ? log ? n ) O(n*\log{n}) On?logn

int n;
int a[N], b[N];
signed main() {
	cf{
		sf(n);
		map<int, vector<int> > q;
		map<int, int> d;
		for (int i = 1; i <= n; i++)
			sf(a[i]), q[a[i]].push_back(i);
		for (int i = 1; i <= n; i++)
			sf(b[i]), d[b[i]] = 0;

		if (a[n] != b[n]) {
			puts("NO");
			continue;
		}

		bool st = true;
		int j = 0;
		for (int i = n - 1; i >= 1 - j; i--)
			if (a[i + j] != b[i]) {
				if (b[i] != b[i + 1] || a[i + j + 1] != b[i + 1]
				        || (int)(lower_bound(all(q[b[i]]), i + j + 1) - q[b[i]].begin()) <= d[b[i]]) {

					if (d[a[i + j]] > 0) {
						d[a[i + j]]--;
						j--;
						i++;
						continue;
					}
					st = false;
					break;
				} else {
					j++;
					d[b[i]]++;
				}
			}
		if (st)
			puts("YES");
		else
			puts("NO");
	}
	return 0;
}

E. notepad.exe

题意:

n n n 个长度未知的字符串数组,你可以进行最多 n + 30 n+30 n+30 次询问。

对于每次询问,你可以定一个宽度 w w w,如果这个宽度比最长的字符串还要短,则会返回 0 0 0 ;否则,在两个相邻字符串之间至少间隔一个空格、每行的长度不超过所给的宽度的情况下,所能够得到的最小的长度 h h h

求该字符串数组能够得到的 h ? w ≠ 0 h*w\neq 0 h?w?=0 的情况下的最小值。

思路:

这道题是赛后补的,交互题实在是有些不擅长。

看到 n + 30 n+30 n+30 次的询问次数,有经验的佬们能看出 30 30 30 代表需要二分,那么我们想下这种情况需要二分什么?
仔细想想,我们能够二分出来的也就只有在 h = = 1 h==1 h==1 的情况下, w w w 的最小值,也就是字符串数组写为一行的宽度。

知道了整个“大”字符串的长度,那么接下就只需要遍历 h h h ,并求出对应的 h ? w h*w h?w,最后取一个最小值即可。

时间复杂度: O ( n ) O(n) On

int ask(int u) {
	cout << "? " << u << '\n';
	fflush(stdout);
	int tmp;
	sf(tmp);
	return tmp;
}
signed main() {
	int n;
	sf(n);
	int l = 1, r = 2010 * 2010;
	while (l < r) {
		int mid = l + r >> 1;
		if (ask(mid) == 1)
			r = mid;
		else
			l = mid + 1;
	}

	int res = l;
	for (int i = 1; i <= n; i++) {
		int x = ask(l / i);
		if (x ) {
			res = min(res, l / i * x);
		}
	}
	cout << "! " << res << "\n";
	return 0;
}

F1. Array Shuffling

题意:

给出一个长度为 n n n 的数组 a a a,并定义一种操作:
选择两个下标 i , j ( 1 ≤ i , j ≤ n ) i,j(1\leq i,j\leq n) ij1i,jn,交换两个下标对应的值。

问怎样将其重新排列,使得得到的数组 b b b 需要最多次操作才能将其还原为 a a a 数组,这里还原的操作为最优解。

思路:

就……很巧,这道题的逆题之前记得佬们聊起过,所以这道题算半个结论题吧,结论与证明 在此。

我们已经知道,想要让还原数组的最少操作次数最多,就要使操作中的环的个数最少;又因为,一个交换操作对应的环中不能有相同的值。
那么做法就很明确了,每次都用最多的不同的数取构造环,然后将环上的值循环错位,直到剩下的数的种类只有一种为止。

时间复杂度: O ( n ) O(n) On

int n;
int s[N];
signed main() {
	cf{
		sf(n);
		map<int, queue<int> > d;
		for (int i = 1; i <= n; i++)
			sf(s[i]), d[s[i]].push(i);

		vector<PII> tmp1;
		for (auto i : d)
			tmp1.push_back({i.y.size(), i.x});
		queue<int> q;
		for (auto i : tmp1)
			q.push(i.y);

		while (q.size() > 1) {
			int len = q.size();
			int t = q.front(), x;
			q.pop();
			if (d[t].size() > 1)
				q.push(t);
			int tmp = d[t].front();
			d[t].pop();
			x = t;
			len--;
			while (len--) {
				int j = q.front();
				q.pop();
				if (d[j].size() > 1)
					q.push(j);
				int v = d[j].front();
				d[j].pop();
				s[v] = t;
				t = j;
			}
			s[tmp] = t;
		}
		for (int i = 1; i <= n; i++)
			pft(s[i]);
		puts("");
	}
	return 0;
}

F2. Checker for Array Shuffling

题意:

思路:

时间复杂度: O ( ) O() O


  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-24 09:40:34  更:2022-04-24 09:40:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:22:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码