edu129div2
A
最优策略是拿最大值。
// Problem: A. Game with Cards
// From: Codeforces - Educational Codeforces Round 129 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1681/problem/A
// Time: 2022-05-23 22:35
// Author: lingfunny
#include <bits/stdc++.h>
using namespace std;
const int mxn = 55;
int n, m, a[mxn], b[mxn];
inline void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", a+i);
scanf("%d", &m);
for(int i = 1; i <= m; ++i) scanf("%d", b+i);
int A = *max_element(a+1, a+n+1), B = *max_element(b+1, b+m+1);
puts(A>=B?"Alice":"Bob");
puts(B>=A?"Bob":"Alice");
}
int main() {
int tt;
scanf("%d", &tt);
while(tt--) solve();
}
B
一眼平衡树。
切牌后循环同构,所以每次切牌相当于走 \(b_i\) 步,直接加起来 \(\bmod n\) 即可。
// Problem: B. Card Trick
// From: Codeforces - Educational Codeforces Round 129 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1681/problem/B
// Time: 2022-05-23 22:35
// Author: lingfunny
#include <bits/stdc++.h>
using namespace std;
const int mxn = 2e5+10;
int a[mxn], n, m;
inline void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", a+i);
int x = 0;
scanf("%d", &m);
for(int i = 1, y; i <= m; ++i) scanf("%d", &y), (x += y) %= n;
++x;
printf("%d\n", a[x]);
}
int main() {
int tt;
scanf("%d", &tt);
while(tt--) solve();
}
C
可排序必须要满足一个二元组比前一个二元组单调不降。
上限是 \(O(n^2)\) 次,冒泡排序排一下,如果排不出来就无解。
// Problem: C. Double Sort
// From: Codeforces - Educational Codeforces Round 129 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1681/problem/C
// Time: 2022-05-23 22:35
// Author: lingfunny
#include <bits/stdc++.h>
using namespace std;
const int mxn = 105, mxs = 1e4+10;
struct node { int a, b; } nd[mxn];
int n, opa[mxs], opb[mxs], tot;
inline void solve() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", &nd[i].a);
for(int i = 1; i <= n; ++i) scanf("%d", &nd[i].b);
tot = 0;
for(int i = n; i; --i) {
for(int j = 1; j < i; ++j)
if(nd[j].a >= nd[j+1].a && nd[j].b >= nd[j+1].b) opa[++tot] = j, opb[tot] = j+1, swap(nd[j], nd[j+1]);
}
for(int i = 1; i < n; ++i) if(nd[i].a > nd[i+1].a || nd[i].b > nd[i+1].b) { puts("-1"); return; }
printf("%d\n", tot);
for(int i = 1; i <= tot; ++i) printf("%d %d\n", opa[i], opb[i]);
}
int main() {
int tt;
scanf("%d", &tt);
while(tt--) solve();
}
D
显然爆搜,\(O(\text{能过})\)。
// Problem: D. Required Length
// From: Codeforces - Educational Codeforces Round 129 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1681/problem/D
// Time: 2022-05-23 22:35
// Author: lingfunny
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int n, ans = 114514;
LL x;
map <LL, int> mp;
void dfs(LL cur, int step) {
if(step >= ans || (mp.find(cur) != mp.end() && mp[cur] <= step)) return;
mp[cur] = step;
// printf("cur = %lld\n", cur);
vector <int> opes;
int length = 0; LL k = cur;
while(k) {
++length;
int x = k % 10;
k /= 10;
if(x > 1) opes.push_back(x);
}
if(length >= n) { ans = min(ans, step); return; }
sort(opes.begin(), opes.end());
opes.resize(unique(opes.begin(), opes.end()) - opes.begin());
for(int x: opes) dfs(cur*x, step+1);
}
signed main() {
scanf("%d%lld", &n, &x);
dfs(x, 0);
printf("%d\n", ans == 114514 ? -1 : ans);
return 0;
}
E
题面怎么这么长,真是钩都不看。跳了跳了。
F
第一眼:树上路径,好像是点分治板子。
20 分钟后:我擦怎么合并不同子树啊草。
第二眼:考虑对于每种边权算贡献。
就是要求断开一些边后,得到的若干棵子树,每条边连接的两棵子树的乘积和。
我暴力短边,用树剖更新节点子树大小,然后查询的时候用并查集跳到这个点属于的子树的根。
要保留祖先关系,不能路径压缩,时间复杂度 \(O(\log^2 n)\),问题不大。
20 分钟后:我擦按秩归并都用不了??要带修并查集??还要维护树的祖先关系??这不相当于 LCT 了???我不会 LCT 啊!??!
我日,ctrl + A, delete, ctrl + S, ctrl + W
。
冷静分析,冷静分析。
考虑按 dfs 序删边,这样好像好做点。
想到前几天看了下 ETT。
把括号序拍下来好像可做?
对于删边操作,就是把序列中的一段连续且大小为 \(2k\) 的点删掉,非常容易更新子树大小。
然后对于删去的子树,在删去的子树中递归进行上面的操作,然后返回这棵子树删边后的大小。
最后 for(int size: son) ans += size * cur_size
。
噫!好!我中了!
时间复杂度分析一下,会发现是按顺序删边的,换句话说 \(O(n)\)。
火速敲代码,时间来到了 0:25。
交!
咚咚咚,Wrong answer on test 7。
谢!
手造几组小样例。
找到 hack 了:
input:
5
1 2 1
2 3 1
3 4 1
4 5 1
answer:
4
output:
15
发生甚么事了呢?
源赖氏佐田,递归下去后没有更新边的顺序。
火速敲代码,时间来到了 0:31
过样例,妙!删 debug,交!
Accepted!
焯!nb!
回头看 E。
剩 2 分钟看个屁。
摆。
// Problem: F. Unique Occurrences
// From: Codeforces - Educational Codeforces Round 129 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1681/problem/F
// Time: 2022-05-23 22:35
// Author: lingfunny
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int mxn = 5e5+10;
int n, dfn[mxn<<1], dfc, L[mxn], R[mxn];
vector <pair<int, int>> G[mxn], E[mxn];
LL ans;
void dfs(int u, int f) {
dfn[L[u] = ++dfc] = u;
for(auto [v, w]: G[u]) if(v != f) E[w].push_back({u, v}), dfs(v, u);
dfn[R[u] = ++dfc] = u;
}
int solve(int Lp, int Rp, int &p, const vector <pair<int, int>> &E) {
vector <int> sub;
int lst = -1, cur = (Rp - Lp + 1)>>1;
for(int i = p; i < (int)E.size(); ++i) {
int v = E[i].second;
if(L[v] > Rp) { p = i-1; break; }
if(lst == -1 || L[v] > R[lst]) lst = v, cur -= (R[v] - L[v] + 1)>>1, sub.push_back((R[v] - L[v] + 1)>>1);
else {
sub.pop_back();
sub.push_back(solve(L[lst], R[lst], i, E));
}
p = i;
}
// printf("[%d -- %d], cur = %d\n", Lp, Rp, cur);
for(int x: sub) ans += (LL)cur*x;
return cur;
}
signed main() {
scanf("%d", &n);
for(int i = 1; i < n; ++i) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
G[u].push_back({v, w});
G[v].push_back({u, w});
}
dfs(1, 0);
for(int i = 1; i <= n; ++i) if(E[i].size()) {
// printf("ans = %lld, i = %d\n", ans, i);
int x = 0;
solve(1, n<<1, x, E[i]);
// printf("ans = %lld, i = %d\n", ans, i);
}
printf("%lld\n", ans);
return 0;
}