admin管理员组文章数量:1622635
文章目录
- Codeforces Round #695 (Div. 2)
- A. Wizard of Orz
- B. Hills And Valleys
- C. Three Bags
- D. Sum of Paths
- E. Distinctive Roots in a Tree
Codeforces Round #695 (Div. 2)
A. Wizard of Orz
题意: 有n个灯,每个灯一开始都是0,每一秒钟每个灯显示的数字会往上一位,但是由于每个灯只能显示单个数位,所以从9增大时得到的是0.在任意时刻,你可以指定唯一一个灯被停止,下一秒后,他相邻的两个灯也会进入暂停状态.问,在合理的设置一个灯被停止之后,所有灯停止,显示的最大的数是多少
**题解: **
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n, m, T;
int main() {
cin >> m;
while(m--) {
cin >> T;
if (T == 1) cout << "9";
else if (T == 2) cout << "98";
else if (T == 3) cout << "989";
else {
cout << "989";
n = 0;
for (int j = 0; j < T - 3; ++j) {
cout << n;
n++;
if (n == 10) n = 0;
}
}
cout << endl;
}
return 0;
}
B. Hills And Valleys
题意: 给定一个长度为n的数组,我们定义山峰为中间点高于两边,定义山谷为中间点低于两边。现在能够改变一个a[i]的权值为任意值,问最少的山峰和山谷数目是多少?
**题解: ** 对于某一个点来说,为了让山峰山谷数目最少,我要不然把它改成前一个点的权值,要不然把它改成后一个点的权值。那么全部都试一下就行了。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int const MAXN = 3e5 + 10;
int n, T;
int a[MAXN];
int solve (int x) {
if (x == 1 || x == n) return 0;
if (a[x - 1] > a[x] && a[x] < a[x + 1]) return 1;
if (a[x - 1] < a[x] && a[x] > a[x + 1]) return 1;
return 0;
}
int main() {
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++) scanf("%d", a + i);
int res = 0;
for (int i = 2; i < n; i++) res += solve(i);
int maxv = 0;
for (int i = 2; i < n; i++) {
int t = a[i];
int X = solve(i - 1) + solve(i) + solve(i + 1);
a[i] = a[i - 1];
int Y = solve(i - 1) + solve(i) + solve(i + 1);
maxv = max(maxv, X - Y);
a[i] = a[i + 1];
Y = solve(i - 1) + solve(i) + solve(i + 1);
maxv = max(maxv, X - Y);
a[i] = t;
}
printf("%d\n", res - maxv);
}
return 0;
}
C. Three Bags
题意: 有三个袋子,每个袋子中有若干个数。我们可以进行如下操作:从袋子 x 中取出数 a , 从另一个袋子 y 中取出数 b ,然后将 a − b放回袋子 x 中。重复操作直到只剩一个数,问我们最后能得到的数最大是多少。
**题解: ** 看到题目就感觉是在数字前面填写+、-号的问题,然后分析了半天也想不出 。题解参考这个大佬:https://blog.csdn/qq_44951010/article/details/112392510?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control
代码:
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
int const MAXN = 300005;
int a[MAXN], b[MAXN], c[MAXN];
int main(void) {
int n1, n2, n3;
scanf("%d%d%d", &n1, &n2, &n3);
LL sum = 0, s1 = 0, s2 = 0, s3 = 0;
for (int i = 0; i < n1 + n2 + n3; ++i) {
int t;
scanf("%d", &t);
if (i < n1)
a[i] = t, s1 += t;
else if (i < n1 + n2)
b[i - n1] = t, s2 += t;
else
c[i - n1 - n2] = t, s3 += t;
}
sum = s1 + s2 + s3;
sort(a, a + n1);
sort(b, b + n2);
sort(c, c + n3);
long long sub = min(s1, min(s2, s3));
sub = min(sub, (LL)a[0] + b[0]);
sub = min(sub, (LL)a[0] + c[0]);
sub = min(sub, (LL)b[0] + c[0]);
printf("%lld\n", sum - 2 * sub);
return 0;
}
D. Sum of Paths
题意: 一个机器人一开始可以从1 ~ n的任意一个位置开始移动,允许移动k步,每次移动k步后形成一条路径,这次移动的贡献值为这条路径上每个点的权值和。机器人所有可以走的路径和为机器人的权值和。现在给定m次操作,每次操作能够使得a[x] = y,问每次机器人的权值和为多少?
**题解: ** 由于本题有m次操作,如果我们能够求出一开始的权值和,那么每次操作只需要修改一个点,减去一个原来的值,加上一个新的值即可。对于权值和,等于每个点的次数 * 每个点的权值。我们可以使用dp来维护每个点出现的次数。
f [ i ] [ j ] f[i][j] f[i][j]:走i步到达j点的方案数。那么有转移方程: f [ i ] [ j ] = ( f [ i − 1 ] [ j + 1 ] + f [ i − 1 ] [ j − 1 ] ) f[i][j] = (f[i - 1][j + 1] + f[i - 1][j - 1]) % mod; f[i][j]=(f[i−1][j+1]+f[i−1][j−1])
然后维护m次操作即可。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 5e3 + 10, mod = 1e9 + 7;
int n, m, T, k;
LL f[MAXN][MAXN], a[MAXN], cnt[MAXN]; // f[i][j]:走i步到达j点的方案数
int main() {
cin >> n >> k >> m;
for (int i = 1; i <= n; ++i) scanf("%lld" , a + i), f[0][i] = 1;
for (int i = 1; i <= k; ++i)
for (int j = 1; j <= n; ++j) {
if (j == 1) f[i][j] = f[i - 1][j + 1];
else if (j == n) f[i][j] = f[i - 1][j - 1];
else f[i][j] = (f[i - 1][j + 1] + f[i - 1][j - 1]) % mod;
}
LL sum = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= k; ++j) {
cnt[i] = (f[j][i] * f[k - j][i] % mod + cnt[i]) % mod;
}
sum = (sum + cnt[i] * a[i]) % mod;
}
for (int i = 1; i <= m; ++i) {
LL x, y;
scanf("%lld%lld", &x, &y);
sum = (((sum - cnt[x] * a[x]) % mod) + mod) % mod;
a[x] = y;
sum = (sum + cnt[x] * a[x] % mod) % mod;
printf("%lld\n", sum);
}
return 0;
}
E. Distinctive Roots in a Tree
题意: 给你一个n个点的无根树,每个点有点权,问你有多少个点满足以它为根的树中每一条根到叶子的路径上都没有权值相同的点。
**题解: ** 题解直接看这个大佬的:https://blog.csdn/forever_shi/article/details/112467674
感觉这个代码好妙呀,直接把2种情况拢在一起写了,然后一种情况分成2半写,要对dfs有很深的理解才能写得出来。想到了思路不知道怎么实现。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10, MAXM = MAXN * 2;
int n, m, T;
int e[MAXM], ne[MAXM], idx, h[MAXN], a[MAXN], tot, dfn[MAXN], cnt, ed[MAXN];
LL sum[MAXN];
unordered_map<int, int> st, num, cur_num;
void add(int a, int b ){
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u, int fa) {
dfn[u] = ++cnt;
int pre1 = cur_num[a[u]];
cur_num[a[u]]++;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa) continue;
int pre2 = cur_num[a[u]];
dfs(j, u);
if (cur_num[a[u]] > pre2) {
sum[1]++;
sum[dfn[j]]--;
sum[ed[j] + 1]++;
}
}
ed[u] = cnt;
if (cur_num[a[u]] - pre1 < num[a[u]]) {
sum[dfn[u]]++;
sum[ed[u] + 1]--;
}
return;
}
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) scanf("%d", a + i), h[i] = -1, num[a[i]]++;
for (int i = 1, a, b; i <= n - 1; ++i) {
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
dfs(1, -1);
int res = 0;
for (int i = 1; i <= n; ++i) {
sum[i] += sum[i - 1];
if (!sum[i]) res++;
}
printf("%d\n", res);
return 0;
}
本文标签: codeforcesDiv
版权声明:本文标题:Codeforces Round #695 (Div. 2) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1728872096a1177382.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论