Codeforces Round #446 (Div. 2)

Codeforces Round #446 (Div. 2)

  • 总体:rating涨了好多,虽然有部分是靠和一些大佬(例如 redbagHometown )交流的……希望下次能自己做出来2333

A. Greed

题意

给你n个罐子,每个罐子都告诉了你它当前的饮料体积和它的总容积,问能否用两个罐子装下所有饮料(n100000

题解

简单模拟即可,用两个最大的算一下,注意累和会爆int

int a[100100], b[100100]; long long sum = 0; int main () { int n = read(); For (i, 1, n) { a[i] = read(); sum += a[i]; } For (i, 1, n) b[i] = read(); sort (b + 1, b + 1 + n); if (b[n] + b[n - 1] >= sum) puts("YES"); else puts("NO"); return 0; }

B. Wrath

题意

给你一个长度为n序列,每个点有个l值,会覆盖他前面l个点,问最后还剩多少个点没有被覆盖。(n100000

题解

应该用差分简单做一下就行了,脑子一抽写了个线段树上去,幸亏过了2333(就当练手吧)

代码

const int N = 1e6 + 1e3; int sum[N << 2]; #define lson o << 1, l, mid #define rson o << 1 | 1, mid + 1, r void Build(int o, int l, int r) { if (l == r) { sum[o] = 1; return ; } int mid = (l + r) >> 1; Build(lson); Build(rson); sum[o] = sum[o << 1] + sum[o << 1 | 1]; } int ul, ur; int lazy[N << 2]; void push_down(int o) { if (!lazy[o]) return; lazy[o << 1] = lazy[o << 1 | 1] = 1; sum[o << 1] = sum[o << 1 | 1] = 0; lazy[o] = 0; } void Update(int o, int l, int r) { if (ul <= l && r <= ur) { lazy[o] = 1; sum[o] = 0; return ;} push_down(o); int mid = (l + r) >> 1; if (ul <= mid) Update(lson); if (ur > mid) Update(rson); sum[o] = sum[o << 1] + sum[o << 1 | 1]; } int main () { int n = read(); Build(1, 1, n); For (i, 1, n) { int len = read(); if (i == 1) continue ; if (!len) continue ; ul = max(i - len, 1); ur = i - 1; Update(1, 1, n); } printf ("%d\n", sum[1]); return 0; }

C. Pride

题意

给你一个长为n序列,你能进行一个操作,将相邻两个数中的一个替换为他们的gcd,问至少进行多少次操作能把他们全部变成1,如果不能完成输出1。(n2000

题解

这题一开始搞了我好久QAQ,想错了。其实就是先弄出一个1,然后可以把其他所有的数字都变成1,剩下的步数就是n1。找那个步数,一定是一段连续区间gcd=1的情况,然后你用O(n2)去枚举一下,找到一个可行的最小长度。还需要特判一开始就有1的情况,不然会挂掉(我就惨遭hack了TAT,后来又hack了两个可怜鬼233)。

代码

const int N = 2010; int a[N], n, ans = 0x7f7f7f7f, res, now; int main () { n = read(); res = n; For (i, 1, n) { a[i] = read(); if (a[i] == 1) -- res; now = __gcd(now, a[i]); } if (now != 1) return puts("-1"), 0; if (res != n) return printf ("%d\n", res), 0; For (i, 1, n) { int here = a[i], len = 0; if (here == 1) { ans = 0; continue ; } Fordown (j, i - 1, 1) { ++ len; here = __gcd(here, a[j]); if (here == 1) { chkmin(ans, len); break; } } } printf ("%d\n", ans + n - 1); return 0; }

D. Gluttony

题意

给你一个长为n序列,其中每个数字都不相同,让你输出一个原序列的一个排列,使得他们中任意一个子集(不能为空集或者全集)的和都互不相同(就是相同位置上的数的和互不相同就行了)(n22

题解

一开始不知道做法,redbag大佬讲出来了正解,就是将每一个数换成后一个比它大的数,最大的数换成最小的那一个,就行了。

证明

这个还是比较好证明的。

考虑分两种情况讨论:

  1. 原子集没有最大的那个数:这就显然是个正确的,每个数都比之前的数要大,所以总和肯定要大;

  2. 原子集有最大的那个数:最大数改变后的值最整个里面最大的,然后你将这个子集去掉最大的那个数,剩下的变化量的和肯定要小于你最大值变为最小值的值,因为你之间肯定会有多余的空格(因为不能为全集)留着,所以肯定是可行的啦。

代码

int n, a[25]; struct node { int val, pos; bool operator < (const node &rhs) const { return val < rhs.val; } }; node lt[25]; int ans[25]; int main () { n = read(); For (i, 1, n) { lt[i].val = read(); lt[i].pos = i; } sort (lt + 1, lt + 1 + n); For (i, 1, n) if (i != n) ans[lt[i].pos] = lt[i + 1].val; else ans[lt[i].pos] = lt[1].val; For (i, 1, n) printf ("%d ", ans[i]); return 0; }

E. Envy

终于来填远古巨坑了。

题意

给你一个有 n 个点 m 条边的带边权无向连通图。

q 次询问,每次询问 k 条边是否能同时存在于 MST (最小生成树)中。(不要求在线回答)

n,m,q,k5×105

题解

首先要知道一个很显然的结论。

就是在 KruskalMST 过程中,我们能否把一条边 (u,v,w) 放入 MST 中,当且仅当 <w 的所有边联通后,u,v 仍然不连通。

所以对于每次询问来说,边权不相同的边是互不影响的,我们可以对于这些边权互不相同的边单独考虑。

相同 w 的如何考虑呢?首先 <w 的边全部加入,然后对于这些边按任意顺序加入的时候,不能存在 (u,v) 相连的情况。

那么就可以得到一个离线算法了。把所有边权按权值排序,一条条加入。然后对于权值相同的同一询问的边,也逐个加入判断是否可行,最后利用可撤销并查集按秩合并的特性,把当前询问的边撤回就行了。

最后复杂度就是 O((m+k)logn) 的。(挂询问用了 std :: map, set 有点慢。。)

代码

还是比较好写的。。

#include <bits/stdc++.h> #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i) #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i) #define Set(a, v) memset(a, v, sizeof(a)) #define Cpy(a, b) memcpy(a, b, sizeof(a)) #define debug(x) cout << #x << ": " << (x) << endl #define DEBUG(...) fprintf(stderr, __VA_ARGS__) #define fir first #define sec second #define mp make_pair using namespace std; typedef pair<int, int> PII; template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; } inline int read() { int x(0), sgn(1); char ch(getchar()); for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1; for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48); return x * sgn; } void File() { #ifdef zjp_shadow freopen ("E.in", "r", stdin); freopen ("E.out", "w", stdout); #endif } const int N = 5e5 + 1e3; struct Edge { int u, v, w; } lt[N]; int Hash[N], tot; struct Data { int u, v, a, b; }; namespace Union_Set { int fa[N], height[N]; int find(int x) { return x == fa[x] ? x : find(fa[x]); } Data stk[N]; int top; inline bool Merge(int u, int v, bool flag) { u = find(u); v = find(v); if (u == v) return false; if (flag) stk[++ top] = (Data) {u, v, height[u], height[v]}; if (height[u] > height[v]) swap(u, v); fa[u] = v; if (height[u] == height[v]) ++ height[v]; return true; } inline void Distract() { Data cur = stk[top --]; height[fa[cur.u] = cur.u] = cur.a; height[fa[cur.v] = cur.v] = cur.b; } } bool ans[N]; map<int, multiset<PII>> M[N]; inline int find_pos(int x) { return lower_bound(Hash + 1, Hash + tot + 1, x) - Hash; } int main () { File(); int n = read(), m = read(); using namespace Union_Set; For (i, 1, n) fa[i] = i; For (i, 1, m) { lt[i].u = read(); lt[i].v = read(); Hash[i] = lt[i].w = read(); } sort(Hash + 1, Hash + m + 1); tot = unique(Hash + 1, Hash + m + 1) - Hash - 1; int q = read(); For (i, 1, m) M[find_pos(lt[i].w)][q + 1].insert(mp(lt[i].u, lt[i].v)); For (i, 1, q) { int k = read(); ans[i] = true; For (j, 1, k) { int id = read(); M[find_pos(lt[id].w)][i].insert(mp(lt[id].u, lt[id].v)); } } For (i, 1, tot) { for (auto itm : M[i]) { if (itm.fir != q + 1 && !ans[itm.fir]) continue ; for (auto its : itm.sec) ans[itm.fir] &= Merge(its.fir, its.sec, itm.fir <= q); while (top) Distract(); } } For (i, 1, q) puts(ans[i] ? "YES" : "NO"); return 0; }

__EOF__

本文作者zjp_shadow
本文链接https://www.cnblogs.com/zjp-shadow/p/7857739.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zjp_shadow  阅读(438)  评论(3编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示