2022 CCPC 绵阳 ACGHM
2022 China Collegiate Programming Contest (CCPC) Mianyang Onsite (2022CCPC绵阳)ACGHM
https://codeforces.com/gym/104065
昨天女队vp了一下,赛时4题223罚时
A是一个dp,学妹已经写的差不多了,就是转移方向错了(给点时间应该能d出来)牛的牛的。我就看了点签到,又是作为蟑螂乱爬的一天
A. Ban or Pick, What's the Trick
记忆化搜索。
状态:\(dp_{i, j, k}\) 表示进行到第 \(i\) 轮,\(A\) 选了 \(j\) 个, \(B\) 选了 \(k\) 个的 \(s_A-s_B\) 的值,然后二者都是从大往小来选(贪心),所以当前选的数也可以通过状态来计算出他所在的下标。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, m, a[N], b[N], f[N][11][11];
bool vis[N][11][11];
int dfs (int x, int ca, int cb) {
if (x >= 2 * n) return 0;
if (vis[x][ca][cb]) return f[x][ca][cb];
vis[x][ca][cb] = true;
int aa = x / 2 - cb + ca + 1, bb = (x + 1) / 2 - ca + cb + 1, &t = f[x][ca][cb];
t = dfs (x + 1, ca, cb); //不选
if (x % 2 == 0) { //A
if (aa <= n && ca < m) t = max (t, dfs (x + 1, ca + 1, cb) + a[aa]);
}
else { //B
if (bb <= n && cb < m) t = min (t, dfs (x + 1, ca, cb + 1) - b[bb]);
}
return t;
}
int main () {
scanf ("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf ("%d", &a[i]);
for (int i = 1; i <= n; i++) scanf ("%d", &b[i]);
sort (a + 1, a + n + 1, greater<int>());
sort (b + 1, b + n + 1, greater<int>());
printf ("%d\n", dfs (0, 0, 0));
}
C. Catch You Catch Me
签到。答案为所有深度为1的点的子树最大深度之和。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 5, M = N * 2;
int n, h[N], e[M], ne[M], idx;
ll dep[N], ans, tt;
bool d[N];
void add (int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dfs (int u, int fa) {
dep[u] = dep[fa] + 1, tt = max (tt, dep[u]);
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa) continue;
dfs (j, u);
}
return tt;
}
int main () {
memset (h, -1, sizeof h);
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
int a, b;
scanf ("%d%d", &a, &b);
add (a, b), add (b, a);
if (a == 1) d[b] = true;
if (b == 1) d[a] = true;
}
for (int i = 1; i <= n; i++) {
if (d[i]) tt = 1, ans += dfs (i, 1);// cout << i << ' ' << tt << endl;
}
printf ("%d\n", ans);
}
G. Let Them Eat Cake
模拟。因为每次至少会删掉一半的数,所以最多进行log次
暴力模拟即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
int n, a[N], ans;
bool vis[N];
int main () {
scanf ("%d", &n);
vector<int> v;
for (int i = 1; i <= n; i++) scanf ("%d", &a[i]), v.push_back (a[i]);
while (1) {
vector<int> tt;
n = v.size ();
if (n == 1) break;
if (v[0] > v[1]) tt.push_back (v[0]);
for (int i = 1; i < n - 1; i++) {
if (v[i] > v[i+1] && v[i] > v[i-1]) tt.push_back (v[i]);
}
if (v[n-1] > v[n-2]) tt.push_back (v[n-1]);
v.clear ();
for (auto i : tt) v.push_back (i);// cout << i << ' ';
//cout << endl;
ans++;
if (v.size () == 1) break;
}
printf ("%d\n", ans);
}
H - Life is Hard and Undecidable, but...
构造一条斜线即可,然而我们想了好久qaq
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main () {
int n;
cin >> n;
cout << 2 * n - 1 << endl;
for (int i = 1; i < 2 * n; i++) cout << i << ' ' << i << endl;
}
M. Rock-Paper-Scissors Pyramid
栈模拟,维护栈内始终是 a 赢 b 的关系
最终答案就是栈底
#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool check (char a, char b) { //a输给b
if (a == b) return true;
if (a == 'S') return b == 'R';
if (a == 'P') return b == 'S';
return b == 'P';
}
void solve () {
string s;
cin >> s;
stack <char> stk;
stk.push (s[0]);
for (int i = 1; i < s.size (); i++) {
while (stk.size () && check (stk.top (), s[i])) stk.pop ();
stk.push (s[i]);
}
while (stk.size () > 1) stk.pop ();
cout << stk.top () << endl;
}
int main () {
int t;
cin >> t;
while (t--) solve ();
}
剩下两题看半天题解看不懂5555我好菜