Codeforces Round #808 (Div. 1)(A~C)

Codeforces Round #808 (Div. 1)(A~C)

A:Doremy's IQ

题目大意

给你一个序列,然后你从左到右可以选择弄或者不弄。
然后你有一个智商值,如果你当前弄的数小于等于它就无影响,否则智商值减一,如果变成了 0 就无法操作。
要你最大化弄的次数,并构造方案。

思路

小溪了这题就卡了半天。
甚至不如先做 T2。

正着我们会有一个 DP,但是似乎不太能优化。
所以考虑反着来,会发现问题就变成了一开始你是 0,每次如果碰到大于的你可以选择 +1 并通过它,然后你只能加到 q
会发现显然可以贪心,就能 +1 就加一,然后模拟一遍过程就好了。

代码

#include<set> #include<map> #include<queue> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #define ll long long //#define mo 998244353 //#define mo 1000000007 using namespace std; const int N = 1e5 + 100; int T, n, q, a[N], jian[N], big, newbig; int ans[N]; int main() { scanf("%d", &T); while (T--) { scanf("%d %d", &n, &q); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), ans[i] = 0; if (q >= n) { for (int i = 1; i <= n; i++) putchar('1'); putchar('\n'); continue; } int now = 0; for (int i = n; i >= 1; i--) if (now < a[i]) { if (now == q) continue; now++; ans[i] = 1; } else { ans[i] = 1; } for (int i = 1; i <= n; i++) printf("%d", ans[i]); printf("\n"); } return 0; }

B:Difference Array

题目大意

给你一个排好序数组,你要对它不断进行以下操作直至数组长度变为 1,并输出最后的数。
把它差分,把差分得到的数组排序。

思路

我只能说有点诈骗。
首先发现数组每一项的和只会最多是数组长度的两倍。

那很多地方都会相同, 那因为一开始就排好序所以差分就会有很多 0
然后你会你只需要保留一个 0 来进行操作,所以真正操作的量会很少。
所以直接模拟即可。

代码

#include<set> #include<map> #include<queue> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #define ll long long //#define mo 998244353 //#define mo 1000000007 using namespace std; const int N = 1e5 + 100; int T, n, a[N], l, r, tmp[N]; void work() { for (int i = l; i < r; i++) tmp[i] = a[i + 1] - a[i]; sort(tmp + l, tmp + r); for (int i = l; i < r; i++) a[i] = tmp[i]; if (l > 1) l--; r--; } int main() { scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); l = 1; r = n; while (l < r && !a[l] && !a[l + 1]) l++; for (int i = 1; i < n; i++) { work(); while (l < r && !a[l] && !a[l + 1]) l++; } printf("%d\n", a[l]); } return 0; }

C:DFS Trees

题目大意

给你一个图,然后问你从每个点出发得到的 dfs 树是否是最小生成树。
每条边边权不同且为 1m 的值。

思路

麻用错性质想了半天。(虽然看起来想法能写但来不及了,主要是想到的性质太复杂啦)

你会发现因为是最小生成树所以你对于一条非树边,你如果从一段走过去,你还是优先走树边。
那怎样会出现问题呢?就是你走完树边,发现到不了非树边连的点,那你就只能走非树边了。
画个图理解一下,你就会发现这些不行的位置都是在非树边两个点之间的路径上的点(以及它的子树),就是中间的部分,你只要从一头进去都是没问题的。

那我们考虑对每条非树边都得到一些判断:
从某些点出发 dfs 可以某些不行,具体一点我们把非树边 x,y 在树上的路径断开,然后 x,y 的子树是可以的。
那如果一个点要完全可以,它要满足每条非树边的条件,那我们就维护每个点满足了多少了条件。
至于子树赋值就直接打标记然后最后跑个 dfs 下传下去即可。

代码

#include<cstdio> #include<vector> using namespace std; const int N = 1e5 + 100; int n, m, fa[N], sum[N], go[N]; vector <int> g[N], G[N], bh[N]; bool tree[N << 1], in[N]; int find(int now) {return fa[now] == now ? now : fa[now] = find(fa[now]);} void dfs(int now, int father) { in[now] = 1; for (int i = 0; i < g[now].size(); i++) { int x = g[now][i]; if (x == father) continue; go[now] = x; dfs(x, now); } for (int i = 0; i < G[now].size(); i++) { int x = G[now][i]; if (tree[bh[now][i]]) continue; tree[bh[now][i]] = 1; if (!in[x]) sum[now]++, sum[x]++; else sum[now]++, sum[1]++, sum[go[x]]--; } in[now] = 0; } void get_sum(int now, int father) { for (int i = 0; i < g[now].size(); i++) { int x = g[now][i]; if (x == father) continue; sum[x] += sum[now]; get_sum(x, now); } } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) fa[i] = i; for (int i = 1; i <= m; i++) { int x, y; scanf("%d %d", &x, &y); if (find(x) != find(y)) fa[find(x)] = find(y), tree[i] = 1, g[x].push_back(y), g[y].push_back(x); else G[x].push_back(y), bh[x].push_back(i), G[y].push_back(x), bh[y].push_back(i); } dfs(1, 0); get_sum(1, 0); for (int i = 1; i <= n; i++) printf("%d", (sum[i] == m - (n - 1)) ? 1 : 0); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/16485973.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(139)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示