Loading

Codeforces Round 998 (Div. 3)



A - Fibonacciness

题意

长度为\(5\)的整数序列,已知\(a_1,a_2,a_4,a_5\),填入一个\(a_3\)使得\(a_{i+2}=a_{i+1}+a_i\)中的\(i\)的个数最多

思路

总的就\(3\)种情况

代码

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;

const int mxn = 1e6 + 5;



void solve()
{
	vector<int> v(5);
	for (int i = 0; i < 5; i++)
	{
		if (i == 2)
		{
			continue;
		}
		cin >> v[i];
	}
	int a = v[0] + v[1];
	int b = v[4] - v[3];
	int c = v[3] - v[1];
	int aa = 0, bb = 0, cc = 0;
	for (int i = 0; i < 3; i++)
	{
		v[2] = a;
		if (v[i + 2] == v[i + 1] + v[i])
		{
			aa++;
		}
		v[2] = b;
		if (v[i + 2] == v[i + 1] + v[i])
		{
			bb++;
		}
		v[2] = c;
		if (v[i + 2] == v[i + 1] + v[i])
		{
			cc++;
		}
	}
	cout << max(aa, max(bb, cc)) << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int T = 1;
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}

B - Farmer John's Card Game

题意

\(n\)头牛编号从\(1\)\(n\),每头牛有\(m\)张手牌,共\(n×m\)张牌编号从\(0\)\(n×m-1\)。构造一个长度为\(n\)的序列\(p\),使得手牌打出的顺序从小到大

思路

\(m=1\),则\(p\)一定存在(手牌大小升序);其他情况最少有\(2n\)张牌,记录每张牌属于哪头牛,用\(ans\)数组存放牛的编号,从小到大遍历手牌,将牛的编号推入\(ans\),直到数组大小为\(2n\),检查前后两部分是否相同,相同就是解,否则无解

代码

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;

const int mxn = 1e6 + 5;

void solve()
{
	int n, m;
	cin >> n >> m;
	set<pii> s;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			int x;
			cin >> x;
			s.insert({ x, i });
		}
	}
	if (m == 1)
	{
		for (auto& i : s)
		{
			cout << i.second << " ";
		}
		cout << endl;
		return;
	}
	vector<int> ans;
	for (auto& i : s)
	{
		ans.push_back(i.second);
		if (ans.size() == n * 2)
		{
			break;
		}
	}
	for (int i = 0; i < n; i++)
	{
		if (ans[i] != ans[i + n])
		{
			cout << -1 << endl;
			return;
		}
	}
	for (int i = 0; i < n; i++)
	{
		cout << ans[i] << " ";
	}
	cout << endl;
	return;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int T = 1;
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}

C - Game of Mathletes

题意

最初有\(n\)个数,初始分数为\(0\)。游戏有\(\frac n 2\)个回合,每回合\(Alice\)先删除一个数记作\(a\)\(Bob\)再删除一个数记作\(b\),若\(a+b=k\),分数加\(1\)\(Alice\)要使分数最小化,\(Bob\)要使分数最大化,两人都以最优方式进行游戏,问最后的得分

思路

显然最后所求即分数的最大值,因为\(Alice\)不管选什么,\(Bob\)总能选到加分的数字(如果有的话)

代码

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;

const int mxn = 1e6 + 5;

void solve()
{
	int n, k, ans = 0;
	cin >> n >> k;
	map<int, int> m;
	vector<bool> vis(n, false);
	for (int i = 0; i < n; i++)
	{
		int x;
		cin >> x;
		m[x]++;
	}
	for (auto& i : m)
	{
		auto p = m.lower_bound(k - i.first); // 找匹配的
		if (p == m.end() || (*p).first != k - i.first)
		{
			continue;
		}
		if (*p == i) // 相等
		{
			ans += i.second / 2;
			i.second = (i.second >> 1 ? 1 : 0);
		}
		else
		{
			if (i.second > (*p).second)
			{
				ans += (*p).second;
				i.second -= (*p).second;
				(*p).second = 0;
			}
			else
			{
				ans += i.second;
				(*p).second -= i.second;
				i.second = 0;
			}
		}
	}
	cout << ans << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int T = 1;
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}


D - Subtract Min Sort

题意

给定正整数序列\(a\),执行以下操作任意次:将\(a_i\)\(a_{i+1}\)减去\(min(a_i,a_{i+1})\)。判断是否能通过操作使得序列不递减。

思路

既然要不递减,那靠前的数自然越小越好,所以可以操作就操作,最后不合法就是无解

代码

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;

const int mxn = 1e6 + 5;

void solve()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	for (int i = 0; i < n - 1; i++)
	{
		if (a[i] <= a[i + 1])
		{
			int t = min(a[i], a[i + 1]);
			a[i] -= t;
			a[i + 1] -= t;
		}
	}
	cout << (is_sorted(a.begin(), a.end()) ? "Yes" : "No") << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int T = 1;
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}


E - Graph Composition

题意

给定两个简单无向图\(F,G\)\(F\)\(m_1\)边,\(G\)\(m_2\)条边。在\(F\)中进行两种操作:删边、加边,使得\(F\)\(G\)连通性相同。求最小操作数

思路

对于\(F\)中多出来的边(相对于\(G\)的连通分量之间)是一定要删的,剩下要加的边就是二者连通分量的数量之差

代码 (参考jiangly)

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
using namespace std;
#define int long long
typedef pair<int, int> pii;

const int mxn = 5e5 + 5;

struct DSU
{
	std::vector<int> f, sz;

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

	void init(int n) 
	{
		f.resize(n);
		std::iota(f.begin(), f.end(), 0);
		sz.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;
		}
		sz[x] += sz[y];
		f[y] = x;
		return true;
	}

	int size(int x) 
	{
		return sz[find(x)];
	}
};

void solve()
{
	int n, m1, m2;
	cin >> n >> m1 >> m2;
	vector<pii> ef(m1);
	DSU f(n), g(n);
	for (int i = 0; i < m1; i++)
	{
		int u, v;
		cin >> u >> v;
		u--, v--;
		ef[i] = { u,v };
	}
	int ans = 0, ccf = n, ccg = n;
	for (int i = 0; i < m2; i++)
	{
		int u, v;
		cin >> u >> v;
		u--, v--;
		ccg -= g.merge(u, v); // g的连通分量
	}
	for (auto& i : ef)
	{
		int u = i.first;
		int v = i.second;
		if (!g.same(u, v))
		{
			ans++; // 删边
		}
		else
		{
			ccf -= f.merge(u, v); // f的连通分量
		}
	}
	cout << ans + ccf - ccg << endl; // 连通分量差值就是要加的边数
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int T = 1;
	cin >> T;
	while (T--)
	{
		solve();
	}

	return 0;
}


比赛链接 https://mirror.codeforces.com/contest/2060

posted @ 2025-02-04 15:26  _SeiI  阅读(157)  评论(0)    收藏  举报