Codeforces Round #446 (Div. 2)
总体:rating涨了好多,虽然有部分是靠和一些大佬(例如 redbag 和 Hometown )交流的……希望下次能自己做出来2333
A. Greed
题意
给你n n 个罐子,每个罐子都告诉了你它当前的饮料体积和它的总容积,问能否用两个罐子装下所有饮料(n ≤ 100000 n ≤ 100000 )
题解
简单模拟即可,用两个最大的算一下,注意累和会爆i n t i n t
B. Wrath
题意
给你一个长度为n n 序列,每个点有个l l 值,会覆盖他前面l l 个点,问最后还剩多少个点没有被覆盖。(n ≤ 100000 n ≤ 100000 )
题解
应该用差分简单做一下就行了,脑子一抽写了个线段树上去,幸亏过了2333(就当练手吧)
代码
C. Pride
题意
给你一个长为n n 序列,你能进行一个操作,将相邻两个数中的一个替换为他们的g c d g c d ,问至少进行多少次操作能把他们全部变成1 1 ,如果不能完成输出− 1 − 1 。(n ≤ 2000 n ≤ 2000 )
题解
这题一开始搞了我好久QAQ,想错了。其实就是先弄出一个1 1 ,然后可以把其他所有的数字都变成1 1 ,剩下的步数就是n − 1 n − 1 。找那个步数,一定是一段连续区间g c d = 1 g c d = 1 的情况,然后你用O ( n 2 ) O ( n 2 ) 去枚举一下,找到一个可行的最小长度。还需要特判一开始就有1 1 的情况,不然会挂掉(我就惨遭hack了TAT,后来又hack了两个可怜鬼233)。
代码
D. Gluttony
题意
给你一个长为n n 序列,其中每个数字都不相同,让你输出一个原序列的一个排列,使得他们中任意一个子集(不能为空集或者全集)的和都互不相同(就是相同位置上的数的和互不相同就行了)(n ≤ 22 n ≤ 22 )
题解
一开始不知道做法,redbag大佬讲出来了正解,就是将每一个数换成后一个比它大的数,最大的数换成最小的那一个,就行了。
证明
这个还是比较好证明的。
考虑分两种情况讨论:
原子集没有最大的那个数:这就显然是个正确的,每个数都比之前的数要大,所以总和肯定要大;
原子集有最大的那个数:最大数改变后的值最整个里面最大的,然后你将这个子集去掉最大的那个数,剩下的变化量的和肯定要小于你最大值变为最小值的值,因为你之间肯定会有多余的空格(因为不能为全集)留着,所以肯定是可行的啦。
代码
E. Envy
终于来填远古巨坑了。
题意
给你一个有 n n 个点 m m 条边的带边权无向连通图。
有 q q 次询问,每次询问 k k 条边是否能同时存在于 M S T M S T (最小生成树)中。(不要求在线回答)
n , m , q , ∑ k ≤ 5 × 10 5 n , m , q , ∑ k ≤ 5 × 10 5
题解
首先要知道一个很显然的结论。
就是在 K r u s k a l K r u s k a l 求 M S T M S T 过程中,我们能否把一条边 ( u , v , w ) ( u , v , w ) 放入 M S T M S T 中,当且仅当 < w < w 的所有边联通后,u , v u , v 仍然不连通。
所以对于每次询问来说,边权不相同的边是互不影响的,我们可以对于这些边权互不相同的边单独考虑。
相同 w w 的如何考虑呢?首先 < w < w 的边全部加入,然后对于这些边按任意顺序加入的时候,不能存在 ( u , v ) ( u , v ) 相连的情况。
那么就可以得到一个离线算法了。把所有边权按权值排序,一条条加入。然后对于权值相同的同一询问的边,也逐个加入判断是否可行,最后利用可撤销并查集按秩合并的特性,把当前询问的边撤回就行了。
最后复杂度就是 O ( ( m + ∑ k ) log n ) O ( ( m + ∑ k ) log n ) 的。(挂询问用了 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__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 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】