Codeforces Round #446 (Div. 2)

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

A. Greed

题意

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

题解

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

  1. int a[100100], b[100100];
  2. long long sum = 0;
  3. int main () {
  4. int n = read();
  5. For (i, 1, n) {
  6. a[i] = read();
  7. sum += a[i];
  8. }
  9. For (i, 1, n)
  10. b[i] = read();
  11. sort (b + 1, b + 1 + n);
  12. if (b[n] + b[n - 1] >= sum)
  13. puts("YES");
  14. else
  15. puts("NO");
  16. return 0;
  17. }

B. Wrath

题意

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

题解

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

代码

  1. const int N = 1e6 + 1e3;
  2. int sum[N << 2];
  3. #define lson o << 1, l, mid
  4. #define rson o << 1 | 1, mid + 1, r
  5. void Build(int o, int l, int r) {
  6. if (l == r) { sum[o] = 1; return ; }
  7. int mid = (l + r) >> 1;
  8. Build(lson); Build(rson);
  9. sum[o] = sum[o << 1] + sum[o << 1 | 1];
  10. }
  11. int ul, ur;
  12. int lazy[N << 2];
  13. void push_down(int o) {
  14. if (!lazy[o]) return;
  15. lazy[o << 1] = lazy[o << 1 | 1] = 1;
  16. sum[o << 1] = sum[o << 1 | 1] = 0; lazy[o] = 0;
  17. }
  18. void Update(int o, int l, int r) {
  19. if (ul <= l && r <= ur) { lazy[o] = 1; sum[o] = 0; return ;}
  20. push_down(o); int mid = (l + r) >> 1;
  21. if (ul <= mid) Update(lson); if (ur > mid) Update(rson);
  22. sum[o] = sum[o << 1] + sum[o << 1 | 1];
  23. }
  24. int main () {
  25. int n = read();
  26. Build(1, 1, n);
  27. For (i, 1, n) {
  28. int len = read();
  29. if (i == 1) continue ;
  30. if (!len) continue ;
  31. ul = max(i - len, 1); ur = i - 1;
  32. Update(1, 1, n);
  33. }
  34. printf ("%d\n", sum[1]);
  35. return 0;
  36. }

C. Pride

题意

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

题解

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

代码

  1. const int N = 2010;
  2. int a[N], n, ans = 0x7f7f7f7f, res, now;
  3. int main () {
  4. n = read();
  5. res = n;
  6. For (i, 1, n) {
  7. a[i] = read();
  8. if (a[i] == 1) -- res;
  9. now = __gcd(now, a[i]);
  10. }
  11. if (now != 1)
  12. return puts("-1"), 0;
  13. if (res != n)
  14. return printf ("%d\n", res), 0;
  15. For (i, 1, n) {
  16. int here = a[i], len = 0;
  17. if (here == 1) {
  18. ans = 0;
  19. continue ;
  20. }
  21. Fordown (j, i - 1, 1) {
  22. ++ len;
  23. here = __gcd(here, a[j]);
  24. if (here == 1) {
  25. chkmin(ans, len);
  26. break;
  27. }
  28. }
  29. }
  30. printf ("%d\n", ans + n - 1);
  31. return 0;
  32. }

D. Gluttony

题意

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

题解

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

证明

这个还是比较好证明的。

考虑分两种情况讨论:

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

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

代码

  1. int n, a[25];
  2. struct node {
  3. int val, pos;
  4. bool operator < (const node &rhs) const {
  5. return val < rhs.val;
  6. }
  7. };
  8. node lt[25];
  9. int ans[25];
  10. int main () {
  11. n = read();
  12. For (i, 1, n) {
  13. lt[i].val = read();
  14. lt[i].pos = i;
  15. }
  16. sort (lt + 1, lt + 1 + n);
  17. For (i, 1, n)
  18. if (i != n)
  19. ans[lt[i].pos] = lt[i + 1].val;
  20. else
  21. ans[lt[i].pos] = lt[1].val;
  22. For (i, 1, n)
  23. printf ("%d ", ans[i]);
  24. return 0;
  25. }

E. Envy

终于来填远古巨坑了。

题意

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

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

\(n, m, q, \sum k \le 5 \times 10^5\)

题解

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

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

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

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

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

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

代码

还是比较好写的。。

  1. #include <bits/stdc++.h>
  2. #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
  3. #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
  4. #define Set(a, v) memset(a, v, sizeof(a))
  5. #define Cpy(a, b) memcpy(a, b, sizeof(a))
  6. #define debug(x) cout << #x << ": " << (x) << endl
  7. #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
  8. #define fir first
  9. #define sec second
  10. #define mp make_pair
  11. using namespace std;
  12. typedef pair<int, int> PII;
  13. template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
  14. template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }
  15. inline int read() {
  16. int x(0), sgn(1); char ch(getchar());
  17. for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
  18. for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
  19. return x * sgn;
  20. }
  21. void File() {
  22. #ifdef zjp_shadow
  23. freopen ("E.in", "r", stdin);
  24. freopen ("E.out", "w", stdout);
  25. #endif
  26. }
  27. const int N = 5e5 + 1e3;
  28. struct Edge {
  29. int u, v, w;
  30. } lt[N];
  31. int Hash[N], tot;
  32. struct Data {
  33. int u, v, a, b;
  34. };
  35. namespace Union_Set {
  36. int fa[N], height[N];
  37. int find(int x) { return x == fa[x] ? x : find(fa[x]); }
  38. Data stk[N]; int top;
  39. inline bool Merge(int u, int v, bool flag) {
  40. u = find(u); v = find(v); if (u == v) return false;
  41. if (flag) stk[++ top] = (Data) {u, v, height[u], height[v]};
  42. if (height[u] > height[v]) swap(u, v); fa[u] = v;
  43. if (height[u] == height[v]) ++ height[v]; return true;
  44. }
  45. inline void Distract() {
  46. Data cur = stk[top --];
  47. height[fa[cur.u] = cur.u] = cur.a;
  48. height[fa[cur.v] = cur.v] = cur.b;
  49. }
  50. }
  51. bool ans[N];
  52. map<int, multiset<PII>> M[N];
  53. inline int find_pos(int x) {
  54. return lower_bound(Hash + 1, Hash + tot + 1, x) - Hash;
  55. }
  56. int main () {
  57. File();
  58. int n = read(), m = read();
  59. using namespace Union_Set;
  60. For (i, 1, n) fa[i] = i;
  61. For (i, 1, m) {
  62. lt[i].u = read();
  63. lt[i].v = read();
  64. Hash[i] = lt[i].w = read();
  65. }
  66. sort(Hash + 1, Hash + m + 1);
  67. tot = unique(Hash + 1, Hash + m + 1) - Hash - 1;
  68. int q = read();
  69. For (i, 1, m)
  70. M[find_pos(lt[i].w)][q + 1].insert(mp(lt[i].u, lt[i].v));
  71. For (i, 1, q) {
  72. int k = read(); ans[i] = true;
  73. For (j, 1, k) {
  74. int id = read();
  75. M[find_pos(lt[id].w)][i].insert(mp(lt[id].u, lt[id].v));
  76. }
  77. }
  78. For (i, 1, tot) {
  79. for (auto itm : M[i]) {
  80. if (itm.fir != q + 1 && !ans[itm.fir]) continue ;
  81. for (auto its : itm.sec)
  82. ans[itm.fir] &= Merge(its.fir, its.sec, itm.fir <= q);
  83. while (top) Distract();
  84. }
  85. }
  86. For (i, 1, q)
  87. puts(ans[i] ? "YES" : "NO");
  88. return 0;
  89. }

Codeforces Round #446 (Div. 2)的更多相关文章

  1. Codeforces Round #446 Div. 1

    B:即使看到n<=22也应该猜到这只是为了写spj.将每个数替换为恰好比他大的数即可,最大值替换为最小值.这样原序列中不包含最小值的集合显然都满足条件,并且容易发现包含最小值的集合的变化量都是最 ...

  2. Codeforces Round #446 (Div. 2) C. Pride【】

    C. Pride time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  3. Codeforces Round #446 (Div. 2) B. Wrath【模拟/贪心】

    B. Wrath time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  4. Codeforces Round #446 (Div. 2) A. Greed【模拟】

    A. Greed time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  5. 【Codeforces Round #446 (Div. 2) C】Pride

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 想一下,感觉最后的结果肯定是从某一段开始,这一段的gcd为1,然后向左和向右扩散的. 则枚举那一段在哪个地方. 我们设这一段中所有的 ...

  6. 【Codeforces Round #446 (Div. 2) B】Wrath

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 倒着来,维护一个最小的点就可以了. [代码] #include <bits/stdc++.h> using namesp ...

  7. 【Codeforces Round #446 (Div. 2) A】Greed

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 贪心选容量大的瓶子就好 [代码] #include <bits/stdc++.h> #define int long l ...

  8. Codeforces Round #366 (Div. 2) ABC

    Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...

  9. Codeforces Round #354 (Div. 2) ABCD

    Codeforces Round #354 (Div. 2) Problems     # Name     A Nicholas and Permutation standard input/out ...

随机推荐

  1. Math Jax开源数学编辑器的使用

    首先,这是一个开源免费,同时也可以支持扩展的软件. 使用API文档: 中文网站(http://mathjax-chinese-doc.readthedocs.io/en/latest/index.ht ...

  2. Linux expect自动登录ssh,ftp

    [http://blog.51yip.com/linux/1462.html#] #!/usr/bin/expect -f set ip 192.168.1.201 set password meim ...

  3. 用户不在sudoers 文件中。此事将被报告 or (usermod:“sudo”组不存在)

    跨平台系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#linux 异常处理汇总-服 务 器 http://www.cnblogs.com/dun ...

  4. JMS学习(一):初识JMS

    1.为什么使用JMS(java消息中间件)java message service 为了解决一个系统对服务调用进行解耦(在一个系统需要调用多个服务的时候,需要通过中间件来进行消息进行交流) 2.AMQ ...

  5. Web API 之承载宿主IIS,SelfHost,OwinSelfHost

            Asp.Net WebAPI这个大家应该都不陌生,在我的理解范围中就是数据提供和交换的一个方式,相比与WCF,WS而言,更加的简单轻量,但是在部署web Api的时候,一般往往需要与a ...

  6. C#委托与事件--后续补充

    委托.事件补充 针对昨天文章 委托:让方法可以跟简单对象一样作为参数进行传递,也就是将方法作为参数进行封装. 方法:本质就是代码段 其实也好理解,目的就是为了封装,多态,既然简单对象如int i可以做 ...

  7. Yii2 Ajax Post 实例及常见错误修正

    先贴下我的代码: signup.js$('.reg_verify_pic').click(function(){ var csrfToken = $('meta[name="_csrf-To ...

  8. Egret学习笔记.1 (写在前面的废话)

    我记得之前谁说过,大部分程序员入行,都是因为小的时候的游戏机啊,各种电子设备啊....觉得有意思,才入的行 . 至少我本人是因为之前上高中那会儿,喜欢玩手机.那会儿还是MTK,塞班的时代,喜欢拿着手机 ...

  9. 阿里云ECS重置磁盘到SSH登录

    1.登录阿里云(www.aliyun.com) -- > 控制台: 2.点击左边的"云服务器ECS": 3.点击上面"第二步",进入页面之后,点击&quo ...

  10. FFmepg 如何在 window 上使用?

    下载FFmepg官网库直接使用即可. avdevice.lib avcodec.lib avfilter.lib avformat.lib avutil.lib postproc.lib swresa ...