传送门

A. Dawid and Bags of Candies

乱搞。

Code
  1. #include <bits/stdc++.h>
  2. #define MP make_pair
  3. #define fi first
  4. #define se second
  5. #define sz(x) (int)(x).size()
  6. //#define Local
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int, int> pii;
  10. const int N = 1e5 + 5;
  11. int a[4];
  12. int main() {
  13. ios::sync_with_stdio(false);
  14. cin.tie(0); cout.tie(0);
  15. cout << fixed << setprecision(20);
  16. #ifdef Local
  17. freopen("../input.in", "r", stdin);
  18. freopen("../output.out", "w", stdout);
  19. #endif
  20. for(int i = 0; i < 4; i++) cin >> a[i];
  21. sort(a, a + 4);
  22. if(a[0] + a[3] == a[1] + a[2] || a[0] + a[1] + a[2] == a[3]) cout << "YES";
  23. else cout << "NO";
  24. return 0;
  25. }

B. Ania and Minimizing

贪心。

Code
  1. #include <bits/stdc++.h>
  2. #define MP make_pair
  3. #define fi first
  4. #define se second
  5. #define sz(x) (int)(x).size()
  6. //#define Local
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int, int> pii;
  10. const int N = 2e5 + 5;
  11. int n, k;
  12. char s[N];
  13. void run() {
  14. cin >> s + 1;
  15. if(n == 1 && k >= 1) {
  16. cout << 0 << '\n'; return;
  17. }
  18. for(int i = 1; i <= n; i++) {
  19. if(i == 1) {
  20. if(s[i] > '1' && k) {
  21. s[i] = '1'; --k;
  22. }
  23. } else {
  24. if(k && s[i] != '0') {
  25. s[i] = '0'; --k;
  26. }
  27. }
  28. }
  29. cout << s + 1 << '\n';
  30. }
  31. int main() {
  32. ios::sync_with_stdio(false);
  33. cin.tie(0); cout.tie(0);
  34. cout << fixed << setprecision(20);
  35. #ifdef Local
  36. freopen("../input.in", "r", stdin);
  37. freopen("../output.out", "w", stdout);
  38. #endif
  39. while(cin >> n >> k) run();
  40. return 0;
  41. }

C. Anadi and Domino

题意:

存在一张图有\(n,n\leq 7\)个点,现在要给他们染上\(1\)~\(6\)的颜色。最后问怎样染色,能够使得\((c_1,c_2)\)这样的对数最多(不计算重复,不考虑顺序,\(c_1,c_2\)表示颜色)。

思路:

一开始想的是随机乱搞一发,结果出了不知道什么错wa了一个点= =

其实直接\(dfs\)就行了,复杂度不会超。

Code
  1. #include <bits/stdc++.h>
  2. #define MP make_pair
  3. #define fi first
  4. #define se second
  5. #define sz(x) (int)(x).size()
  6. //#define Local
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int, int> pii;
  10. const int N = 10;
  11. int n, m;
  12. int ans, res;
  13. vector <int> g[N];
  14. int c[N];
  15. bool chk[N][N];
  16. void dfs(int x) {
  17. if(x == n + 1) {
  18. res = 0;
  19. for(int i = 1; i <= n; i++) {
  20. for(auto it : g[i]) {
  21. chk[c[i]][c[it]] = 1;
  22. }
  23. }
  24. for(int i = 1; i <= 6; i++) {
  25. for(int j = i; j <= 6; j++) {
  26. if(chk[i][j]) {
  27. ++res;
  28. chk[i][j] = 0;
  29. }
  30. }
  31. }
  32. ans = max(ans, res);
  33. return;
  34. }
  35. for(int i = 1; i <= 6; i++) {
  36. c[x] = i;
  37. dfs(x + 1);
  38. }
  39. }
  40. void run() {
  41. for(int i = 1; i <= m; i++) {
  42. int u, v; cin >> u >> v;
  43. g[u].push_back(v);
  44. g[v].push_back(u);
  45. }
  46. dfs(1);
  47. cout << ans << '\n';
  48. }
  49. int main() {
  50. ios::sync_with_stdio(false);
  51. cin.tie(0); cout.tie(0);
  52. cout << fixed << setprecision(20);
  53. #ifdef Local
  54. freopen("../input.in", "r", stdin);
  55. freopen("../output.out", "w", stdout);
  56. #endif
  57. while(cin >> n >> m) run();
  58. return 0;
  59. }

D. Marcin and Training Camp

题意:

先有\(n\)个人,每个人有两个属性:\(a,b\)。其中\(a\)的含义是,当前这个人会一些技能,技能的\(id\)就为\(a\)里面二进制\(1\)的位置。

\(i\)看不起\(j\),当且仅当\(i\)会一项\(j\)不会的技能。

现在要选择一些人出来作为一支团队,要求不存在一个人看不起其它所有人并且\(b\)的和最大。

思路:

题意不好描述啊感觉= =

首先可以发现一个比较显然的结论:

  • 团队中最大的\(a\)值至少有两个。

因为要\(b\)和最大,所以有推论:

  • 若存在多个人的\(a\)相同,那么他们都可以选择。

处理完上面的情况,剩下的就是\(a\)只出现一次了。接下来又有一个结论:

  • 一个\(a\)能够被选择,当且仅当他作为已选集合的一个子集。

如果不满足上面的条件,那么他就能够看不起其它所有人,除非有其他人\(a\)值和他相同,但这种情况已经排除了。

然后随便写写就好了。

Code
  1. #include <bits/stdc++.h>
  2. #define MP make_pair
  3. #define fi first
  4. #define se second
  5. #define sz(x) (int)(x).size()
  6. //#define Local
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int, int> pii;
  10. const int N = 7006;
  11. struct People{
  12. ll a, b;
  13. bool operator < (const People &A) const {
  14. if(a == A.a) return b < A.b;
  15. return a < A.a;
  16. }
  17. }p[N], t[N];
  18. int n;
  19. void run() {
  20. for(int i = 1; i <= n; i++) cin >> t[i].a;
  21. for(int i = 1; i <= n; i++) cin >> t[i].b;
  22. sort(t + 1, t + n + 1);
  23. ll ans = 0;
  24. int tot = 0;
  25. vector <ll> S;
  26. for(int i = 1, j; i <= n; i = j) {
  27. ll tmp = 0, cnt = 0;
  28. j = i;
  29. while(j <= n && t[i].a == t[j].a) {
  30. tmp += t[j].b;
  31. ++cnt; ++j;
  32. }
  33. if(cnt > 1) {
  34. ans += tmp;
  35. S.push_back(t[i].a);
  36. } else {
  37. p[++tot] = t[i];
  38. }
  39. }
  40. for(int i = 1; i <= tot; i++) {
  41. int ok = 0;
  42. for(auto it : S) {
  43. if((p[i].a & it) == p[i].a) ok = 1;
  44. }
  45. if(ok) {
  46. ans += p[i].b;
  47. // S.push_back(p[i].a);
  48. }
  49. }
  50. cout << ans << '\n';
  51. }
  52. int main() {
  53. ios::sync_with_stdio(false);
  54. cin.tie(0); cout.tie(0);
  55. cout << fixed << setprecision(20);
  56. #ifdef Local
  57. freopen("../input.in", "r", stdin);
  58. freopen("../output.out", "w", stdout);
  59. #endif
  60. while(cin >> n) run();
  61. return 0;
  62. }

E. Kamil and Making a Stream

题意:

给出一颗树,每个结点都有其权值,先求所有链的\(gcd\)的和。

思路:

  • 比较直接的想法就是\(O(n^2)\)的暴力,对于每个点\(v\),找到其所有的祖先\(u\),计算\(gcd\)。
  • 稍微改进一下,不用找到所有的祖先,只需要找到其父亲与所有祖先的\(gcd\)值就行,但复杂度还是没有变。
  • 发现\(gcd\)的个数很少,大概为\(\log_{2}a[v]\)个,因为每个\(gcd\)都为\(a[v]\)因子。所以直接用一个\(map\)来存一下出现次数就行了。

似乎这里\(map\)的\(log\)和\(gcd\)的\(log\)的分开的...

Code
  1. #include <bits/stdc++.h>
  2. #define MP make_pair
  3. #define fi first
  4. #define se second
  5. #define sz(x) (int)(x).size()
  6. //#define Local
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int, int> pii;
  10. const int N = 1e5 + 5, MOD = 1e9 + 7;
  11. int n;
  12. ll a[N];
  13. vector <int> g[N];
  14. unordered_map <ll, int> mp[N];
  15. ll ans;
  16. void dfs(int u, int fa) {
  17. for(auto it : mp[fa]) {
  18. ll now = __gcd(it.fi, a[u]);
  19. mp[u][now] += it.se;
  20. }
  21. ++mp[u][a[u]];
  22. for(auto it : mp[u]) {
  23. ans = (ans + it.fi * it.se % MOD) % MOD;
  24. }
  25. for(auto v : g[u]) {
  26. if(v != fa) dfs(v, u);
  27. }
  28. }
  29. void run() {
  30. for(int i = 1; i <= n; i++) cin >> a[i];
  31. for(int i = 1; i < n; i++) {
  32. int u, v; cin >> u >> v;
  33. g[u].push_back(v);
  34. g[v].push_back(u);
  35. }
  36. dfs(1, 0);
  37. cout << ans << '\n';
  38. }
  39. int main() {
  40. ios::sync_with_stdio(false);
  41. cin.tie(0); cout.tie(0);
  42. cout << fixed << setprecision(20);
  43. #ifdef Local
  44. freopen("../input.in", "r", stdin);
  45. freopen("../output.out", "w", stdout);
  46. #endif
  47. while(cin >> n) run();
  48. return 0;
  49. }

F. Konrad and Company Evaluation

题意:

给出一个\(n\)个点\(m\)条边的有向图,现在有\(q\)次操作,每次可以选择一个点,然后将它所有的入边反转。

问每次操作过后形成的“三元环”数量,这里“三元环”的定义为对于点\(a,b,c\),有\(a->b->c\),那么这就算作一个。

\(n,m,q\leq 10^5\)。

思路:

  • 统计三元环时,易知一个点的贡献为\(out[u]*in[u]\),相当于枚举中点。

问题在于每次如何翻转边并且快速统计答案。然后题解就是暴力翻转就行了...

下面简略证明一下:

  • 我们按照每个点的度从大到小排序,并且以度数为\(\sqrt{2m}\)划分界限,左边为“大点”,右边为“小点”。
  • 易知左边点的个数不会超过\(\sqrt{2m}\)个,而右边点的度数不会超过\(\sqrt{2m}\)。
  • 现在将所有边分为三类:在“大点”间的,在“小点”间的,以及跨过中线的,然后依次分析:
    • 显然每次对“小点”操作不会超过\(\sqrt{2m}\);
    • 对于跨过中间的,我们先消耗一定复杂度让其全部指向“小点”,易知复杂度不超过\(O(m)\)。
    • 那么每次对“大点”操作,第一类复杂度不会超过\(\sqrt{2m}\)(因为个数只有那么多),对于第三类边,只有可能一开始已经翻转过,那么这类边每次操作的复杂度最高为\(O(T)\),\(T\)表示当前时间。所以对于一个“大点”而言,操作一次的最高复杂度为\(O(q+\sqrt{2m})\),最多操作\(\sqrt{2m}\)次。
  1. * 综上,总的复杂度为$O(q\sqrt{2m}+m)$的样子。

然后暴力就行啦,感觉证明的思想核心还是对度数进行分块然后来分析,挺巧妙的~其实简单点想就是,对于每个点只有可能第一次翻转复杂度较高,后面翻转就跟时间有关了,因为每次翻转对于一个点入度最多增加\(1\)。

代码很简单:

Code
  1. #include <bits/stdc++.h>
  2. #define MP make_pair
  3. #define fi first
  4. #define se second
  5. #define sz(x) (int)(x).size()
  6. //#define Local
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int, int> pii;
  10. const int N = 1e5 + 5;
  11. int n, m;
  12. vector <int> in[N];
  13. int d[N];
  14. void run() {
  15. for(int i = 1; i <= m; i++) {
  16. int u, v; cin >> u >> v;
  17. if(u > v) swap(u, v);
  18. ++d[u], ++d[v];
  19. in[u].push_back(v);
  20. }
  21. ll ans = 0;
  22. for(int i = 1; i <= n; i++) ans += 1ll * (d[i] - sz(in[i])) * sz(in[i]);
  23. int q; cin >> q;
  24. while(q--) {
  25. cout << ans << '\n';
  26. int x; cin >> x;
  27. ans -= 1ll * (d[x] - sz(in[x])) * sz(in[x]);
  28. for(auto v : in[x]) {
  29. ans -= 1ll * (d[v] - sz(in[v])) * sz(in[v]);
  30. in[v].push_back(x);
  31. ans += 1ll * (d[v] - sz(in[v])) * sz(in[v]);
  32. }
  33. in[x].clear();
  34. }
  35. cout << ans << '\n';
  36. }
  37. int main() {
  38. ios::sync_with_stdio(false);
  39. cin.tie(0); cout.tie(0);
  40. cout << fixed << setprecision(20);
  41. #ifdef Local
  42. freopen("../input.in", "r", stdin);
  43. freopen("../output.out", "w", stdout);
  44. #endif
  45. while(cin >> n >> m) run();
  46. return 0;
  47. }

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

  1. Codeforces Round #588 (Div. 2)-E. Kamil and Making a Stream-求树上同一直径上两两节点之间gcd的和

    Codeforces Round #588 (Div. 2)-E. Kamil and Making a Stream-求树上同一直径上两两节点之间gcd的和 [Problem Description ...

  2. Codeforces Round #588 (Div. 2) E. Kamil and Making a Stream(DFS)

    链接: https://codeforces.com/contest/1230/problem/E 题意: Kamil likes streaming the competitive programm ...

  3. Codeforces Round #588 (Div. 2) D. Marcin and Training Camp(思维)

    链接: https://codeforces.com/contest/1230/problem/D 题意: Marcin is a coach in his university. There are ...

  4. Codeforces Round #588 (Div. 2) C. Anadi and Domino(思维)

    链接: https://codeforces.com/contest/1230/problem/C 题意: Anadi has a set of dominoes. Every domino has ...

  5. Codeforces Round #588 (Div. 2) B. Ania and Minimizing(构造)

    链接: https://codeforces.com/contest/1230/problem/B 题意: Ania has a large integer S. Its decimal repres ...

  6. Codeforces Round #588 (Div. 2) A. Dawid and Bags of Candies

    链接: https://codeforces.com/contest/1230/problem/A 题意: Dawid has four bags of candies. The i-th of th ...

  7. Codeforces Round #588 (Div. 1)

    Contest Page 因为一些特殊的原因所以更得不是很及时-- A sol 不难发现当某个人diss其他所有人的时候就一定要被删掉. 维护一下每个人会diss多少个人,当diss的人数等于剩余人数 ...

  8. Codeforces Round #588 (Div. 1) 简要题解

    1. 1229A Marcin and Training Camp 大意: 给定$n$个对$(a_i,b_i)$, 要求选出一个集合, 使得不存在一个元素好于集合中其他所有元素. 若$a_i$的二进制 ...

  9. Codeforces Round #588 (Div. 2) D题【补题ING】

    思路:先找出现次数>=2数.然后在取跑所有数,需要考虑一般情况(当一个人比另一个人的ai小且他们的与运算等于小的那个人的ai那么可以知道大的那个人必定强于ai小的那个人). 则可以用位运算实现判 ...

随机推荐

  1. Selenium(九):Xpath选择器

    1. Xpath选择器 1.1 Xpath语法简介 前面我们学习了CSS选择元素. 大家可以发现非常灵活.强大. 还有一种灵活.强大的选择元素的方式,就是使用Xpath表达式. XPath (XML ...

  2. html中的a标签详解

    事故起源于一个魔鬼测试人员,某天做网站UI优化的时候,突然甩了一个问题给我 第二列的数据是可以跳转至其他页面的,但是,魔鬼测试的电脑上,一直都有一条数据是与其他的样式不同,于是便甩了这个问题给我,我一 ...

  3. Django 执行 makemigrations 显示 No changes detected in app

    在Django项目配置一下多数据库,但是运行 makemigrations 执行不正常 $ python manage.py makemigrations polls No changes detec ...

  4. 团队项目之测试与发布(Alpha版本)

    小组:BLACK PANDA 时间:2019.12.05 测试报告 1.测试找出的BUG 图片上传,文件过大会出错 用户可访问不具权限的URL 空字段导致异常 serializable反序列化时版本不 ...

  5. Excel 2003 与 Excel 2007之间有什么不同?

    如果您使用Excel 2003已有数年,您可能会意识到使用更多最新版本的Excel(2007.2010.2013或Excel 2016)的人员或组织的数量正在增加.您甚至可能收到了自己的Excel工作 ...

  6. 22(7).模型融合---CatBoost

    一.Catboost简介 全称:Gradient Boosting(梯度提升) + Categorical Features(类别型特征) 作者:俄罗斯的搜索巨头Yandex 官方地址 论文链接 | ...

  7. C#的语法----程序结构(2)

    接下来我们继续学习程序流程控制的语法! switch-case 用来处理多条件的定值的判断. 语法: switch(变量或者表达式的值) { case value1:要执行的代码1: break; c ...

  8. java对 zip文件的压缩和解压(ant解决中文乱码)

    说明: 1.对于压缩的文件,当文件名称是中文时,若使用JDK API中自带的类(java.util.zip.ZipEntry; java.util.zip.ZipOutputStream;)进行压缩, ...

  9. Python动态网页爬虫-----动态网页真实地址破解原理

    参考链接:Python动态网页爬虫-----动态网页真实地址破解原理

  10. 23.login1(SKCTF)

    没有账号?注册一个试一试~ 题目提示用SQL约束攻击,那么什么是SQL约束攻击呢? 约束攻击的原理就是注册用户名为'admin    '(有多个空格)的账号,密码'*******'(密码可以自定义,符 ...