Educational Codeforces Round 143 (Rated for Div. 2)

Problem - B Ideal Point

给定n个线段区间\([l,r]\),我们定义\(f(x)\)为覆盖点\(x\)的线段数,我们每次操作可以删除任意一条线段,并且操作数不限,给出q次询问,每次询问点x能否通过操作使得\(f(x)\)严格最大

题解:贪心

我们通过模拟发现只要把不包含x的线段全部删除,那么仍然存在的线段都会限制\(f(x)\),然后如果存在其他点y使得\(f(y)>=f(x)\)或者存在,那么说明我们无论如何都不能使得\(f(x)\)最大,反之一定可以,由于数据比较小,直接通过计数数组\(cnt\)判断即可

  1. #include <bits/stdc++.h>
  2. #define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
  3. #define debug(x) cerr << #x << '=' << x << endl
  4. #define all(x) (x).begin(), (x).end()
  5. #define rson id << 1 | 1
  6. #define lson id << 1
  7. #define int long long
  8. #define mpk make_pair
  9. #define endl '\n'
  10. using namespace std;
  11. typedef unsigned long long ULL;
  12. typedef long long ll;
  13. typedef pair<int, int> pii;
  14. typedef pair<ll, ll> pll;
  15. const int inf = 0x3f3f3f3f;
  16. const ll INF = 0x3f3f3f3f3f3f3f3f;
  17. const int mod = 1e9 + 7;
  18. const double eps = 1e-9;
  19. const int N = 2e5 + 10, M = 4e5 + 10;
  20. int n, k;
  21. pii a[55];
  22. void solve()
  23. {
  24. cin >> n >> k;
  25. for (int i = 1; i <= n; ++i)
  26. cin >> a[i].first >> a[i].second;
  27. vector<int> cnt(55, 0);
  28. int ok = 0;
  29. for (int i = 1; i <= n; ++i)
  30. {
  31. if (a[i].first <= k && k <= a[i].second)
  32. {
  33. for (int j = a[i].first; j <= a[i].second; ++j)
  34. cnt[j]++;
  35. }
  36. }
  37. int maxx = -INF, num = 0;
  38. for (int i = 1; i <= 50; ++i)
  39. maxx = max(cnt[i], maxx);
  40. for (int i = 1; i <= 50; ++i)
  41. if (cnt[i] == maxx)
  42. num++;
  43. if (cnt[k] == maxx && num == 1)
  44. cout << "YES" << endl;
  45. else
  46. cout << "NO" << endl;
  47. }
  48. signed main(void)
  49. {
  50. Zeoy;
  51. int T = 1;
  52. cin >> T;
  53. while (T--)
  54. {
  55. solve();
  56. }
  57. return 0;
  58. }

Problem - C Tea Tasting

给定n杯茶,每杯茶有\(a_i\)毫升,每杯茶面前都有一个品茶人,每次能够喝\(b_i\)毫升的茶,每一轮品茶结束后所有人都会往左移动,也就是说第一回合结束后第一个人不会再喝茶,第二回合结束后第二个人不会再喝茶,那么每个人在每回合能够喝到茶的数量为\(min(a_i,b_i)\),请你求出所有人分别能够喝到的茶的数量

题解:二分+前缀和+差分

首先我们可以知道对于第\(i\)杯茶来说,只有\([i+1,n]\)这些人能够喝到,所以我们可以先求出每个人喝茶\(b_i\)的前缀和\(pre\),对于每杯茶我们只需要二分前缀和找到后面第一个喝不满\(b_j\)这个茶的人\(j\),那么我们只要让\(j\)喝完剩下所有茶,然后利用差分数组记录中间都能喝满自己能喝的茶的人即可;

注意:这边在二分前缀和的时候有个技巧,我们对于每个\(a_i\)都要去往\(i\)的后面找,也就是说所有\(i\)后面的前缀和都要减去\(pre[i-1]\),比较麻烦,那么我们这边大佬有个技巧就是我们直接\(a_i+pre[i-1]\),这样效果也是一样,我只能说太秀

  1. #include <bits/stdc++.h>
  2. #define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
  3. #define debug(x) cerr << #x << '=' << x << endl
  4. #define all(x) (x).begin(), (x).end()
  5. #define rson id << 1 | 1
  6. #define lson id << 1
  7. #define int long long
  8. #define mpk make_pair
  9. #define endl '\n'
  10. using namespace std;
  11. typedef unsigned long long ULL;
  12. typedef long long ll;
  13. typedef pair<int, int> pii;
  14. typedef pair<ll, ll> pll;
  15. const int inf = 0x3f3f3f3f;
  16. const ll INF = 0x3f3f3f3f3f3f3f3f;
  17. const int mod = 1e9 + 7;
  18. const double eps = 1e-9;
  19. const int N = 2e5 + 10, M = 4e5 + 10;
  20. int n;
  21. int pre[N];
  22. void solve()
  23. {
  24. cin >> n;
  25. vector<int> ans(n + 10);
  26. vector<int> a(n + 10), b(n + 10);
  27. vector<int> dif(n + 10);
  28. for (int i = 1; i <= n; ++i)
  29. cin >> a[i];
  30. for (int i = 1; i <= n; ++i)
  31. cin >> b[i];
  32. for (int i = 1; i <= n; ++i)
  33. pre[i] = pre[i - 1] + b[i];
  34. for (int i = 1; i <= n; ++i)
  35. {
  36. int pos = upper_bound(pre + 1, pre + n + 1, a[i] + pre[i - 1]) - pre;
  37. ans[pos] += a[i] - (pre[pos - 1] - pre[i - 1]);
  38. dif[i]++;
  39. dif[pos]--;
  40. }
  41. for (int i = 1; i <= n; ++i)
  42. dif[i] = dif[i - 1] + dif[i];
  43. for (int i = 1; i <= n; ++i)
  44. {
  45. ans[i] += b[i] * dif[i];
  46. cout << ans[i] << " ";
  47. }
  48. cout << endl;
  49. }
  50. signed main(void)
  51. {
  52. Zeoy;
  53. int T = 1;
  54. cin >> T;
  55. while (T--)
  56. {
  57. solve();
  58. }
  59. return 0;
  60. }

Problem - D Triangle Coloring

给定n个节点和n条边,每条边存在权值,并且\(6|n\),将每三个节点变成一个三元组,并用三条边连接,现在需要将n个点中一半的点涂成红色,一半的点涂成蓝色,如果两个点颜色不一样,那么连接这两个点的边的权值会被记录在sum中,最后你需要使得sum最大,并且求出使得sum最大的方案数

题解:组合计数+思维

首先n个点中一半为红色,一半为蓝色,很明显在一个三元组内,我们只有两种涂色方式:

  1. 全为红色或蓝色;
  2. 一红二蓝或者一蓝二红;

显然后者对于sum的贡献更大,我们取后者

假设一个三元组需要涂一红二蓝,也就是说我们在每个三元组中会选择两条边,那么存在以下几种情况:

  1. 每条边的权值都不一样,我们肯定会选择最大的两条,那么只有一种选择
  2. 最小两条边的权值相同,那么我们肯定会选择最大的以及任意一条最小边,有两种选择;
  3. 如果三条边的权值都相同,我们任意选择两条边即可,有3种选择;

那儿我们还需要知道哪些三元组涂了一红二蓝,哪些涂了一蓝二红,答案乘上\(C_{n/3}^{n/6}\)即可

注意:因为取模运算没有除法,所以我们需要利用快速幂求出乘法逆元,\(C_{n/3}^{n/6} = \frac{A_{n/3}^{n/6}}{A_{n/6}^{n/6}}\)

  1. #include <bits/stdc++.h>
  2. #define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
  3. #define debug(x) cerr << #x << '=' << x << endl
  4. #define all(x) (x).begin(), (x).end()
  5. #define rson id << 1 | 1
  6. #define lson id << 1
  7. #define int long long
  8. #define mpk make_pair
  9. #define endl '\n'
  10. using namespace std;
  11. typedef unsigned long long ULL;
  12. typedef long long ll;
  13. typedef pair<int, int> pii;
  14. typedef pair<ll, ll> pll;
  15. const int inf = 0x3f3f3f3f;
  16. const ll INF = 0x3f3f3f3f3f3f3f3f;
  17. const int mod = 998244353;
  18. const double eps = 1e-9;
  19. const int N = 3e5 + 10, M = 4e5 + 10;
  20. int qpow(int x, int y)
  21. {
  22. int res = 1;
  23. while (y)
  24. {
  25. if (y & 1)
  26. res = res * x % mod;
  27. x = x * x % mod;
  28. y >>= 1;
  29. }
  30. return res;
  31. }
  32. int A(int n, int m)
  33. {
  34. int res = 1;
  35. for (int i = m; i > m - n; --i)
  36. res = res * i % mod;
  37. return res;
  38. }
  39. int n;
  40. int a[4];
  41. void solve()
  42. {
  43. cin >> n;
  44. int ans = 1;
  45. for (int i = 1; i <= n; i += 3)
  46. {
  47. cin >> a[1] >> a[2] >> a[3];
  48. sort(a + 1, a + 4);
  49. if (a[1] == a[2] && a[2] == a[3])
  50. ans = ans * 3 % mod;
  51. else if (a[1] == a[2])
  52. ans = ans * 2 % mod;
  53. }
  54. ans = ans * A(n / 6, n / 3) % mod;
  55. ans = ans * qpow(A(n / 6, n / 6), mod - 2) % mod;
  56. cout << ans << endl;
  57. }
  58. signed main(void)
  59. {
  60. Zeoy;
  61. int T = 1;
  62. // cin >> T;
  63. while (T--)
  64. {
  65. solve();
  66. }
  67. return 0;
  68. }

Problem - E Explosions?

给定n个怪兽,每个怪兽血量为\(h_i\),你现在有两种魔法:

  1. 消耗1MP,对一个怪兽的血量减去1,可以释放无数次
  2. 消耗xMP,对于一个怪兽的血量减去x,如果该怪兽死亡,会引起连锁反应,他会对它相邻两边的怪兽产生爆炸伤害\(h_i-1\),如果该伤害继续造成死亡,会继续往旁边造成爆炸伤害,直到没有造成死亡为止,只能在最后一次释放

注意:怪物的位置不能移动,即使怪物死了,也不会消失

请你求出最少需要多少MP才能消灭所有怪物

题解:维护二元单调栈+贪心 :好题目

根据贪心思想,我们最好在最后一步爆炸解决掉所有的怪兽,所以我们可以枚举在每一个怪兽位置爆炸需要的MP,最后取min即可

那么为了实现最后的爆炸能够清除所有的怪兽,我们需要保证数组h要形成一个单峰,引爆位置左边严格递增,引爆位置右边严格递减,那么假设使得左边严格递增的花费为\(L[i]\),右边严格递减的花费为\(R[i]\),那么选择i位置作为引爆点的全部花费为\(L[i]+R[i]+h[i]\)

现在的关键就是如何求出L[i]和R[i],我们先对于L[i]进行讨论,R[i]可以同理得出:

我们可以维护一个单调递增栈,栈中元素是个二元组\((val,cnt)\)表示一个集合:val代表集合中最大值,cnt代表集合中有cnt个数,并且该集合是一个严格递增且差值为1的集合,那么很明显我们可以知道集合中的最小值为\(val-cnt+1\)

那么我们遍历数组\(h\)维护单调递增栈,我们讨论以下情况对单调栈内的集合进行合并和插入:

  1. 如果当前集合的最小值\(val-cnt+1>\)栈顶集合的最大值,直接将插入集合\((h[i],1)\)

  2. 如果当前集合的最小值\(val-cnt+1<=\)栈顶集合的最大值,那么我们需要将集合进行合并,合并的过程需要代价,并将栈顶不断出栈,直到不能合并为止,比如栈顶为(3,1),待插入的集合为(2,1),那么合并后的集合应该为(2,2),所以花费应该为3-2=1,因为我们需要的是一个单调递增且差值为1的集合

再举个例子,(3,3)和(3,2)合并,也就是(1,2,3)和(2,3)合并,那么我们需要的代价就是为了方便先把(1,2,3)变为(0,0,0)然后再变成(0,0,1),所以需要的代价为(1+2+3-1),那么这个代价我们可以利用等差数列求和快速实现

根据这样的操作我们就能够计算出L[i],同理我们从后往前遍历维护单调递增栈,即可求出\(R[i]\)

下面给出一个样例,并附上图示,便于理解集合的合并和为什么这样能够得出L[i]和R[i]:

  1. #include <bits/stdc++.h>
  2. #define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
  3. #define debug(x) cerr << #x << '=' << x << endl
  4. #define all(x) (x).begin(), (x).end()
  5. #define rson id << 1 | 1
  6. #define lson id << 1
  7. #define int long long
  8. #define mpk make_pair
  9. #define endl '\n'
  10. using namespace std;
  11. typedef unsigned long long ULL;
  12. typedef long long ll;
  13. typedef pair<int, int> pii;
  14. typedef pair<ll, ll> pll;
  15. const int inf = 0x3f3f3f3f;
  16. const ll INF = 0x3f3f3f3f3f3f3f3f;
  17. const int mod = 1e9 + 7;
  18. const double eps = 1e-9;
  19. const int N = 3e5 + 10, M = 4e5 + 10;
  20. int n;
  21. pii stk[N];
  22. int h[N], L[N], R[N];
  23. int tt;
  24. int cal(int x, int n)
  25. {
  26. int p = max(0ll, x - n + 1);
  27. return n * (p + x) / 2;
  28. }
  29. void solve()
  30. {
  31. cin >> n;
  32. tt = 0;
  33. for (int i = 1; i <= n; ++i)
  34. cin >> h[i];
  35. int sum = 0;
  36. for (int i = 1; i <= n; ++i)
  37. {
  38. int cnt = 1;
  39. while (tt && h[i] - cnt + 1 <= stk[tt].first)
  40. {
  41. int minn = max(0ll, h[i] - cnt + 1); //防止最小值为负数
  42. sum += cal(stk[tt].first, min(stk[tt].first, stk[tt].second));
  43. sum -= cal(max(0ll, minn - 1), min(max(0ll, minn - 1), stk[tt].second));
  44. cnt += stk[tt].second;
  45. tt--;
  46. }
  47. L[i] = sum;
  48. stk[++tt] = mpk(h[i], cnt);
  49. }
  50. tt = 0;
  51. sum = 0;
  52. for (int i = n; i >= 1; --i)
  53. {
  54. int cnt = 1;
  55. while (tt && h[i] - cnt + 1 <= stk[tt].first)
  56. {
  57. int minn = max(0ll, h[i] - cnt + 1);
  58. sum += cal(stk[tt].first, min(stk[tt].first, stk[tt].second));
  59. sum -= cal(max(0ll, minn - 1), min(max(0ll, minn - 1), stk[tt].second));
  60. cnt += stk[tt].second;
  61. tt--;
  62. }
  63. R[i] = sum;
  64. stk[++tt] = mpk(h[i], cnt);
  65. }
  66. int ans = INF;
  67. for (int i = 1; i <= n; ++i)
  68. ans = min(ans, h[i] + L[i] + R[i]);
  69. cout << ans << endl;
  70. }
  71. signed main(void)
  72. {
  73. Zeoy;
  74. int T = 1;
  75. cin >> T;
  76. while (T--)
  77. {
  78. solve();
  79. }
  80. return 0;
  81. }

Educational Codeforces Round 143 (Rated for Div的更多相关文章

  1. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  2. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  3. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  4. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  5. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  6. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  7. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  8. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

  9. Educational Codeforces Round 48 (Rated for Div. 2) CD题解

    Educational Codeforces Round 48 (Rated for Div. 2) C. Vasya And The Mushrooms 题目链接:https://codeforce ...

  10. Educational Codeforces Round 60 (Rated for Div. 2) 题解

    Educational Codeforces Round 60 (Rated for Div. 2) 题目链接:https://codeforces.com/contest/1117 A. Best ...

随机推荐

  1. java基础(非常简单)

    java javaSE 注释: block块级 line 行 标识符和关键字 组成部分.变量名.类名.方法名--------标识符 $\数字._\字母 数据类型 强类型语言---安全性高--速度会慢 ...

  2. noip2020模拟赛 背包 (knapsack)

    题目 区间 \(01\) 背包 \(1 \le l_i \le r_i \le n \le 20000,1 \le q \le 100000,1 \le m_i \le 500, 1 \le w_i ...

  3. 不借助脚手架手动搭建react项目(webpack5 + Antd4 + React18)

    前言 工作中发现很多同事在接到一个新项目时,总是基于现有项目复制一份配置文件,然后写自己的组件及业务代码,以至于项目中存在一些冗余的依赖及配置信息.并且由于已有项目的依赖包及插件比较老,新项目也一直没 ...

  4. 内网安全之:Windows系统帐号隐藏

    Windows系统帐号隐藏 目录 Windows系统帐号隐藏 1 CMD下创建隐藏账户 2 注册表创建隐藏账户 3 利用工具隐藏账户 1 CMD下创建隐藏账户 CMD下创建隐藏账户 net user ...

  5. python爬取网页的多种方式以及保存方法

    爬取网页信息并保存 bs4和lxml都是用来将接收的数据解析html 1.bs4+excel(openpyxl): import requests from bs4 import BeautifulS ...

  6. Vue学习笔记之计算属性、内容分发、自定义事件

    1. 计算属性 计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化 ...

  7. JavaWeb中的Servlet

    Servlet 目录 Servlet 一.互联网中的资源 二.Servlet 2.1.Servlet的作用 2.2.Servlet执行流程 2.3.Servlet生命周期 2.4.Servlet的继承 ...

  8. 【win+r】快速打开软件

    第一种设置方法: ①把要启动的文件夹路径添加到系统环境变量里面去 ②按win+r就可以快速启动了 第二种设置方法: 是直接把(程序的)快捷方式,放到安装目录的 Windows\System32\ 文件 ...

  9. FTP调优

    最近在解决客户的问题时接触到了一些FTP的问题,自己在使用过程中发现了很多问题,所以这里总结了一些调优的办法: 服务:vsftp 非常安全文件传输 配置文件:/etc/vsftpd/vsftpd.co ...

  10. MySQL5.7升级版本到8.0

    升级二进制包安装的MySQL In-Place Upgrade(替代升级) 替代升级涉及到shutdown down旧版本的MySQL,用新版本的包替代旧版本的二进制包,用存在的数据文件目录重启MyS ...