正常了一把,可惜没过了E
前两题也没啥好讲的,看代码就🆗
1337A Ichihime and Triangle A.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 #include <bits/stdc++.h> using namespace std ;int main () { int q; cin >> q; while (q--) { int a, b, c, d; cin >> a >> b >> c >> d; cout << b << ' ' << c << ' ' << c << endl ; } return 0 ; }
1337B Kana and Dragon Quest game B.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <bits/stdc++.h> using namespace std ;int main () { int q; cin >> q; while (q--) { int x, n, m; cin >> x >> n >> m; while (x > 0 ) { if (n && x > 20 ) --n, x = x / 2 + 10 ; else if (m) --m, x -= 10 ; else break ; } if (x > 0 ) puts ("NO" ); else puts ("YES" ); } return 0 ; }
1336A Linova and Kingdom 有一颗以$1$为根的树,把$k$个点涂成黑色,问每个黑色点到根的路径上白色点数量的和是多少。
如果一个点涂黑了,意味着这颗子树全部被涂黑了,那么讨论这个点(的子树除了自己全部涂色后)涂色对答案的贡献,即 $(dpt_i-1)sz_i-dpt_i(sz_i-1)$,排序后取前$n-k$大就是答案,$O(n\log n)$,题解提到如果用 $STL$ 的 $nth_element()$ 部分排序可以做到$O(n)$。
C.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <bits/stdc++.h> using namespace std ;typedef long long ll;const int N = 2e5 + 5 ;ll cnt[N], dpt[N]; vector <int > g[N];vector <pii> ps;void dfs (int u, int fa) { for (int v : g[u]) { if (v == fa) continue ; dpt[v] = dpt[u] + 1 ; dfs(v, u); cnt[u] += cnt[v]; } ++cnt[u]; ps.emplace_back(u, (dpt[u] - 1 ) * cnt[u] - dpt[u] * (cnt[u] - 1 )); } int main () { int n, k; cin >> n >> k; for (int i = 1 , u, v; i < n; ++i) { cin >> u >> v; g[u].emplace_back(v); g[v].emplace_back(u); } dpt[1 ] = 1 ; dfs(1 , 0 ); ll ans = 0 ; sort(ps.begin (), ps.end (), [&](pii a, pii b) { return a.second > b.second; }); for (int i = 0 ; i < k; ++i) { ans += ps[i].second; } cout << ans << endl ; return 0 ; }
1336B Xenia and Colorful Gems 有三种颜色的宝石,每个宝石都有权值,要求每个颜色的宝石取一个,问能取的最小的$(x-y)^2+(y-z)^2+(z-x)^2$是多少。
如果我们将取得得三个值排序,那么两边得数越接近中间的,答案就越小。因此枚举中间值,二分找另外两个数,$O(n\log n)$。
D.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5 + 5 ; ll ans; int a[3 ] [N] , n[3 ] ;void calc(int q, int w, int e) { for (int i = 0 ; i < n[q ] ; ++i) { auto p2 = lower_bound(a [w ], a [w ] + n [w ], a [q ][i ]) - a[w ] ; auto p3 = upper_bound(a [e ], a [e ] + n [e ], a [q ][i ]) - a[e ] ; if (p3 != 0 ) --p3; if (p2 == n[w ] ) --p2; ll x = a[q ] [i ] , y = a[w ] [p2 ] , z = a[e ] [p3 ] ; ans = min(ans, (x - y) * (x - y) + (x - z) * (x - z) + (y - z) * (y - z)); p2 = upper_bound(a [w ], a [w ] + n [w ], a [q ][i ]) - a[w ] ; p3 = lower_bound(a [e ], a [e ] + n [e ], a [q ][i ]) - a[e ] ; if (p2 != 0 ) --p2; if (p3 == n[e ] ) --p3; x = a[q ] [i ] , y = a[w ] [p2 ] , z = a[e ] [p3 ] ; ans = min(ans, (x - y) * (x - y) + (x - z) * (x - z) + (y - z) * (y - z)); } } int main() { int q; cin >> q; while (q--) { cin >> n[0 ] >> n[1 ] >> n[2 ] ; for (int i = 0 ; i < 3 ; ++i) { for (int j = 0 ; j < n[i ] ; ++j) { cin >> a[i ] [j ] ; } sort(a[i ] , a[i ] + n[i ] ); } ans = LLONG_MAX; calc(0 ,1 ,2 ); calc(1 ,0 ,2 ); calc(2 ,1 ,0 ); cout << ans << endl; } return 0 ; }
1336C Kaavi and Magic Spell 感觉挺开拓思维的一道题 其实是我$dp$太差想不到 有两个字符串$s,t$和一个空串$a$,现在每次操作可以把$s$的首字母添加到$a$的头或尾,问在所有的操作序列中,产生的$a$以$t$为前缀个序列个数,具体题意请看样例解释 吧。
正解是区间$dp$,设$dp[l][r]$为操作第$x$个字母后,与$t[l][r]$匹配的$a$的个数,那么:
当枚举到第$x$个字母时,$r=l+x-1$;
当$s_x == t_l$时,也就是说可以从$dp[l+1][r]$转移到$dp[l][r]$;
当$s_x == t_r$时,也就是说可以从$dp[l][r-1]$转移到$dp[l][r]$;
对于上述的$l,r>m$时,因为已经不会影响匹配,就可以直接转移;
当$x=1$时,需要从$dp[i][i-1]$转移一下,此时设为$1$即可; 答案即$\sum_{i=m}^n dp[1][i]$,$O(n^2)$
E.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <bits/stdc++.h> using namespace std ;int main () { string s, t; cin >> s >> t; int n = s.length(), m = t.length(); s = ' ' + s, t = ' ' + t; vector <vector <int >> dp (n + 2 , vector <int > (n + 2 )) ; for (int i = 1 ; i <= n + 1 ; ++i) { dp[i][i - 1 ] = 1 ; } for (int i = 1 ; i <= n; ++i) { for (int l = 1 ; l <= n - i + 1 ; ++l) { int r = l + i - 1 ; if (l > m || s[i] == t[l]) dp[l][r] = (dp[l][r] + dp[l + 1 ][r]) % mod; if (r > m || s[i] == t[r]) dp[l][r] = (dp[l][r] + dp[l][r - 1 ]) % mod; } } int ans = 0 ; for (int i = m; i <= n; ++i) { ans = (ans + dp[1 ][i]) % mod; } cout << ans << endl ; return 0 ; }
本文标题: Codeforces Round 635 Div.2 题解
文章作者: WGree
发布时间: 2020-04-16
最后更新: 2020-04-17
原始链接: https://blog.wgree.site/3213635929/
版权声明: 禁止转载