Codeforces Round 977 (Div. 2, based on COMPFEST 16 - Final Round)
A. Meaning Mean
题目链接: Problem - A - Codeforces
题目描述:
给定一个包含 ( n ) 个正整数的数组 ( a )。你可以执行如下操作直到数组中只剩下一个元素:
- 从数组中选择两个不同的元素 ( a_i ) 和 ( a_j ),计算 ( \lfloor \frac{a_i + a_j}{2} \rfloor )(向下取整)。
-
- 将该值加入数组末尾,并移除选取的 ( a_i ) 和 ( a_j )。 要求找出经过所有操作后,数组中剩下的唯一元素 ( x ) 的最大可能值。
解题思路:
这是一个贪心问题。为了最大化最后一个元素的值,每次操作都应尽量选择值相近的两个元素进行计算。这样可以减少对中间值的损失,保持最终结果尽可能大。实现时,可以使用一个优先队列(堆)来维护数组元素,每次弹出两个最小值进行计算,直到只剩下一个元素。
C++代码实现:
#include <map>
#include <set>
#include <fstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <bitset>
#include <iomanip>
#define endl '\n'
#define int long long
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
signed main()
{
BoBoowen;
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
vector<long long> a(n);
for (auto &x : a)
{
cin >> x;
}
priority_queue<long long, vector<long long>, std::greater<long long>> pq(a.begin(), a.end());
while (pq.size() > 1)
{
long long first = pq.top();
pq.pop();
long long second = pq.top();
pq.pop();
long long new_val = (first + second) / 2;
pq.push(new_val);
}
cout << pq.top() << endl;
}
return 0;
}
B. Maximize Mex
题目链接: Problem - B - Codeforces
题目描述:
给定一个包含 ( n ) 个正整数的数组 ( a ) 和一个整数 ( x )。你可以多次将数组中的任意元素加上 ( x )。要求计算数组的最大 (\operatorname{MEX}) 值。 (\operatorname{MEX}) 指的是数组中未出现的最小非负整数。
解题思路:
我们需要优化数组的 MEX 值。为了保证更高的 MEX,应该优先填充从 0 开始缺失的数值。每次尽量将小于 MEX 的元素通过加 ( x ) 的操作进行补全。可以通过计数数组记录出现的值,再逐个检查缺失的最小值即可。
C++代码实现:
#include <map>
#include <set>
#include <fstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <bitset>
#include <iomanip>
#define endl '\n'
#define int long long
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
void solve()
{
int n, x;
cin >> n >> x;
vector<int> cnt(n + 1, 0);
for (int i = 0; i < n; ++i)
{
int a;
cin >> a;
if (a <= n)
{
cnt[a]++;
}
}
for (int i; i < n + 1; ++i)
{
if (cnt[i] == 0)
{
cout << i << endl;
return;
}
int tmp = cnt[i] - 1;
if (i + x <= n)
{
cnt[i + x] += tmp;
}
}
}
signed main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}
C1. Adjust The Presentation (Easy Version)
题目链接: Problem - C1 - Codeforces
题目描述:
有一个包含 ( n ) 名成员的团队准备展示一场幻灯片演示。幻灯片有 ( m ) 张,编号从 1 到 ( m )。每张幻灯片由当前站在队伍最前面的成员展示,展示后可以将该成员移动到队伍的任意位置。要求在一系列更新操作之后,确保队伍能够按照指定的成员顺序展示所有幻灯片。
解题思路:
这是一个模拟问题,每次更新后检查当前队伍顺序是否满足条件。可以使用队列来模拟成员的移动,逐次检查每个幻灯片是否能按要求展示。由于这是简单版本,我们只需要在每次更新后检查队伍状态。
C++代码实现:
#include <map>
#include <set>
#include <fstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <bitset>
#include <iomanip>
#define endl '\n'
#define int long long
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
const int N = 2e5 + 5;
int T, n, a[N], m, q, b[N], s[N];
void solve()
{
cin >> n >> m >> q;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
s[i] = m + 1;
}
for (int i = 1; i <= m; i++)
{
cin >> b[i];
}
for (int i = 1; i <= m; i++)
{
if (s[b[i]] == m + 1)
{
s[b[i]] = i;
}
}
for (int i = 1; i < n; i++)
{
if (s[a[i]] > s[a[i + 1]])
{
cout << "TIDAK" << endl;
return;
}
}
cout << "YA" << endl;
}
signed main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}
C2. Adjust The Presentation (Hard Version)
题目链接: Problem - C2 - Codeforces
题目描述:
这是问题 C 的困难版。区别在于更新操作的数量增加,最多可达 2⋅1052 \cdot 10^52⋅105。在每次更新之后,同样需要判断队伍是否可以按照指定顺序展示幻灯片。
解题思路:
由于更新次数非常多,需要使用高效的数据结构来处理队伍状态变化。我们可以使用集合来快速维护每个成员展示幻灯片的顺序,通过比较前后顺序的关系,来判断更新后是否满足要求。需要在每次更新时高效地更新集合和状态。
C++代码实现:
#include <map>
#include <set>
#include <fstream>
#include <queue>
#include <deque>
#include <stack>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdio>
#include <bitset>
#include <iomanip>
#define endl '\n'
#define int long long
#define Max(a, b) (((a) > (b)) ? (a) : (b))
#define Min(a, b) (((a) < (b)) ? (a) : (b))
#define BoBoowen ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
using namespace std;
const int N = 2e5 + 1;
const int inf = 2e9;
int v[N], who[N];
int p[N], n;
set<int> st[N];
int ans;
void xiu(int id, int x, bool f, bool s)
{
if (id != 1 && f)
{
int p1, p2;
if (st[id - 1].size() == 0)
{
p1 = inf;
}
else
{
p1 = *st[id - 1].begin();
}
if (st[id].size() == 0)
{
p2 = inf;
}
else
{
p2 = *st[id].begin();
}
ans += x * (p1 > p2);
}
if (id != n && s)
{
int p1, p2;
if (st[id].size() == 0)
{
p1 = inf;
}
else
{
p1 = *st[id].begin();
}
if (st[id + 1].size() == 0)
{
p2 = inf;
}
else
{
p2 = *st[id + 1].begin();
}
ans += x * (p1 > p2);
}
}
void clear()
{
for (int i = 1; i <= n; ++i)
{
st[i].clear();
}
}
signed main()
{
BoBoowen;
int t;
cin >> t;
while (t--)
{
int m, q, x, y;
cin >> n >> m >> q;
for (int i = 1; i <= n; ++i)
{
cin >> v[i];
p[v[i]] = i;
}
for (int i = 1; i <= m; ++i)
{
cin >> who[i];
st[p[who[i]]].insert(i);
}
ans = 0;
for (int i = 2; i <= n; ++i)
{
int p1, p2;
if (st[i - 1].size() == 0)
{
p1 = inf;
}
else
{
p1 = *st[i - 1].begin();
}
if (st[i].size() == 0)
{
p2 = inf;
}
else
{
p2 = *st[i].begin();
}
ans += (p1 > p2);
}
if (ans == 0)
{
cout << "YA" << endl;
}
else
{
cout << "TIDAK" << endl;
}
while (q--)
{
cin >> x >> y;
int id1 = p[who[x]], id2 = p[y];
xiu(id1, -1, true, true);
xiu(id2, -1, (id1 != id2 - 1), (id1 != id2 + 1));
st[id1].erase(x);
who[x] = y;
st[id2].insert(x);
xiu(id1, +1, true, true);
xiu(id2, +1, (id1 != id2 - 1), (id1 != id2 + 1));
if (ans == 0)
{
cout << "YA" << endl;
}
else
{
cout << "TIDAK" << endl;
}
}
clear();
}
return 0;
}