• CF Edu129 div2


    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;
    }	
    
  • 相关阅读:
    Java 小记 — Spring Boot 的实践与思考
    Docker 小记 — Compose & Swarm
    Linux 小记 — 网络管理
    Docker 小记 — Docker Engine
    Nginx 原理解析和配置摘要
    笔记与随想 — 解决问题
    Mac 小记 — 杂录
    编剧小记 — Contour
    Linux 小记 — Ubuntu 自动化配置
    dotnetcore 自动迁移工具
  • 原文地址:https://www.cnblogs.com/lingfunny/p/16361119.html
Copyright © 2020-2023  润新知