Codeforces Round 875 (Div. 2)【A、B、C】

文章包含了三道编程题目:A题是构造一个与原排列和单调不减的排列;B题涉及贪心策略,计算在两个数组合并过程中最大连续相同的次数;C题是关于树的DFS,求解从根节点出发的有向树最少需要多少轮才能完全绘制。每道题都提供了C++代码实现。
摘要由CSDN通过智能技术生成


传送门

A. Twin Permutations(构造)

题意:给出排列a,让你给出排列b,使得两排列之和单调不减
思路:构造全相等的排列
时间复杂度:O(n)

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
using namespace std;
const int N = 105, mod = 998244353;
int a[N];
void solve() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> a[i];
	for (int i = 1; i <= n; i++) cout << n + 1 - a[i] << " \n"[i == n];
} 
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T = 1;
 	cin >> T;
	while (T--) {
		solve();
	}
	return 0; 
}

B. Array merging(贪心)

题意:给你两个数组,每次取a第一个或者取b第一个得到c数组,问你最大的连续相同次数。
思路:如何理解这种操作,实际上就是在a数组中插入b数组,首先可以统计a数组中的答案(注意,这也是答案的一部分),统计所有的数的最大连续出现次数。插入b数组后这些答案一定不会更差,由于插入并不能改变b数组的顺序,我们将b数组划分成若干块,一步步插入,如果有更优的答案记录。
时间复杂度:O(n)/O(nlogn)][用map]

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
using namespace std;
const int N = 2e5 + 5, mod = 998244353;
int a[N], b[N];
void solve() {
	int n;
	cin >> n;
	int ans = 0;
	map<int, int> mp;
	for (int i = 1; i <= n; i++) cin >> a[i];
	int cnt = 0, p = a[1];
	for (int i = 1; i <= n; i++) {
		if (a[i] == p) cnt++;
		else {
			ans = max(cnt, ans);
			mp[p] = max(mp[p], cnt);
			cnt = 1;
			p = a[i];
		}
	} 
	if (cnt) ans = max(ans, cnt), mp[p] = max(mp[p], cnt), cnt = 0;
	p = b[1];
	for (int i = 1; i <= n; i++) cin >> b[i];
	for (int i = 1; i <= n; i++) {
		if (p == b[i]) cnt++;
		else {
			ans = max(mp[p] + cnt, ans);
			cnt = 1;
			p = b[i];
		}
	}
	if (cnt) ans = max(mp[p] + cnt, ans);
	cout << ans << '\n';
} 
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T = 1;
 	cin >> T;
	while (T--) {
		solve();
	}
	return 0; 
}

C. Copil Copac Draws Trees(DFS)

题意:按照输入顺序我们至少要看一次才能画出这棵树,只有边的一端和根联通的才能画上去。
思路:按照输入顺序,我们给从根出发的有向树的较深的边进行编号。从根开始出发,进行dfs,我们考虑,根画到这个点最多要画几轮,这样就转化为一个非常经典的问题了。就是求下降的次数,因为前面的边必须先画,所以,后面的边序号反而小的话就要再过一轮,答案取最大就行。
时间复杂度:O(n)

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define ll long long
using namespace std;
const int N = 2e5 + 5, mod = 998244353;
vector<int> g[N];
int from[N], to[N], d[N], num[N];
void dfs(int u, int fa) {
	for (auto v : g[u]) {
		if (v == fa) continue;
		d[v] = d[u] + 1;
		dfs(v, u);
	}
}
int ans;
void dfs1(int u, int fa, int cnt) {
	ans = max(ans, cnt);
	for (auto v : g[u]) {
		if (v == fa) continue;
		if (num[v] < num[u]) dfs1(v, u, cnt + 1);
		else dfs1(v, u, cnt);
	}
}
void solve() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) g[i].clear();
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		from[i] = u, to[i] = v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1, 0);
	for (int i = 1; i < n; i++) {
		int u = from[i], v = to[i];
		if (d[u] > d[v]) num[u] = i;
		else num[v] = i; 
	}
	ans = 1;
	dfs1(1, 0, 1);
	cout << ans << '\n';
} 
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T = 1;
 	cin >> T;
	while (T--) {
		solve();
	}
	return 0; 
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值