传送门

A - The Fool

整除分块即可。

B - The World

模拟即可。

C - Justice

题意:

给出\(n\)个数\(k_i\),每个数的权值为\(\frac{1}{2^{k_i}}\)。

现在问能否将这些数划分为两个集合,使得每个集合里面数的权值和不小于\(\frac{1}{2}\)。

若合法,输出任意一种方案。

思路:

  • 对于两个相同的\(k\),一定能够合并为\(k-1\)。
  • 直接数组存储显然存不下,我们可以直接合并到\(k-x\),满足\(k-x\)存在,也就是说我们每次将\(a_i\)减小到\(a_{i-1}\),时间复杂度最多为\(O(logn)\)。
  • 模拟这个过程就行了,后面输出方案的时候找到一个阀值即可。

说起来感觉比较简单,写起来没那么简单,细节很多。。后面寻找方案的时候也套了个二分(可能我姿势水平太低了)。

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 all(x) (x).begin(), (x).end()
  7. // #define Local
  8. using namespace std;
  9. typedef long long ll;
  10. typedef pair<int, int> pii;
  11. const int N = 1e5 + 5;
  12. int n;
  13. pii a[N], b[N], c[N];
  14. int Case;
  15. int bel[N], ans[N];
  16. bool ok(int x, int y) {
  17. while(x != 1 && y >= 2) {
  18. --x; y /= 2;
  19. }
  20. if(x == 1) return true;
  21. return false;
  22. }
  23. void run() {
  24. ++Case;
  25. cin >> n;
  26. for(int i = 1; i <= n; i++) {
  27. cin >> a[i].fi;
  28. a[i].se = i;
  29. bel[i] = ans[i] = 0;
  30. }
  31. sort(a + 1, a + n + 1);
  32. int tot = 0;
  33. for(int i = 1, j; i <= n; i = j) {
  34. j = i;
  35. while(j <= n && a[i].fi == a[j].fi) ++j;
  36. b[++tot] = MP(a[i].fi, j - i);
  37. for(int k = i; k < j; k++) bel[k] = tot;
  38. }
  39. b[0] = MP(1, 0);
  40. for(int i = 0; i <= tot; i++) c[i] = b[i];
  41. for(int i = tot; i > 0; i--) {
  42. int x = b[i].se;
  43. int now = b[i].fi, pre = b[i - 1].fi;
  44. while(now != pre && x >= 2) {
  45. x /= 2;
  46. --now;
  47. }
  48. if(now == pre) b[i - 1].se += x;
  49. }
  50. cout << "Case " << Case << ": ";
  51. if(b[0].se >= 2) {
  52. cout << "YES" << '\n';
  53. } else {
  54. cout << "NO" << '\n';
  55. return;
  56. }
  57. if(a[1].fi == 1) {
  58. ans[a[1].se] = 1;
  59. for(int i = 1; i <= n; i++) {
  60. cout << ans[i];
  61. }
  62. cout << '\n';
  63. return;
  64. }
  65. int need = 0, t = 0;
  66. for(int i = tot; i > 0; i--) {
  67. int x = c[i].se;
  68. int now = c[i].fi, pre = c[i - 1].fi;
  69. if(ok(now, x)) {
  70. int l = 1, r = x + 1, mid;
  71. while(l < r) {
  72. mid = (l + r) >> 1;
  73. if(ok(now, mid)) r = mid;
  74. else l = mid + 1;
  75. }
  76. t = tot + 1, need = r; break;
  77. }
  78. while(now != pre && x >= 2) {
  79. x /= 2;
  80. --now;
  81. }
  82. if(now != pre) x = 0;
  83. int k1 = c[i - 1].fi, k2 = c[i - 1].se + x;
  84. if(ok(k1, k2)) {
  85. int l = x, r = k2 + 1, mid;
  86. while(l < r) {
  87. mid = (l + r) >> 1;
  88. if(ok(k1, mid)) r = mid;
  89. else l = mid + 1;
  90. }
  91. need = r - x; t = i; break;
  92. }
  93. c[i - 1].se += x;
  94. }
  95. for(int i = 1; i <= n; i++) {
  96. if(bel[i] >= t) {
  97. ans[a[i].se] = 1;
  98. } else if(bel[i] == t - 1 && need) {
  99. ans[a[i].se] = 1; --need;
  100. } else ans[a[i].se] = 0;
  101. }
  102. for(int i = 1; i <= n; i++) {
  103. cout << ans[i];
  104. }
  105. cout << '\n';
  106. }
  107. int main() {
  108. ios::sync_with_stdio(false);
  109. cin.tie(0); cout.tie(0);
  110. cout << fixed << setprecision(20);
  111. #ifdef Local
  112. freopen("../input.in", "r", stdin);
  113. freopen("../output.out", "w", stdout);
  114. #endif
  115. int T; cin >> T;
  116. while(T--) run();
  117. return 0;
  118. }

 

有一种更加简单优美的做法:并查集+优先队列。

并查集就维护合并路径,还是比较巧妙。

细节见代码:

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 all(x) (x).begin(), (x).end()
  7. // #define Local
  8. using namespace std;
  9. typedef long long ll;
  10. typedef pair<int, int> pii;
  11. const int N = 1e5 + 5;
  12. int n;
  13. int a[N];
  14. int Case;
  15. int f[N];
  16. int find(int x) {
  17. return f[x] == x ? f[x] : f[x] = find(f[x]);
  18. }
  19. void run() {
  20. cout << "Case " << ++Case << ": ";
  21. cin >> n;
  22. for(int i = 1; i <= n; i++) cin >> a[i];
  23. for(int i = 0; i <= n; i++) {
  24. f[i] = i;
  25. }
  26. priority_queue <pii> q;
  27. for(int i = 1; i <= n; i++) {
  28. q.push(pii(a[i], i));
  29. }
  30. while(!q.empty() && q.top().fi > 1) {
  31. pii now = q.top(); q.pop();
  32. if(q.empty()) break;
  33. if(now.fi != q.top().fi) continue;
  34. pii cur = q.top(); q.pop();
  35. int fx = find(now.se), fy = find(cur.se);
  36. if(fx < fy) swap(fx, fy);
  37. f[fx] = fy;
  38. q.push(pii(now.fi - 1, fy));
  39. }
  40. if(q.size() <= 1) {
  41. cout << "NO" << '\n';
  42. } else {
  43. cout << "YES" << '\n';
  44. for(int i = 1; i <= n; i++) {
  45. if(find(i) == q.top().se) cout << 1;
  46. else cout << 0;
  47. }
  48. cout << '\n';
  49. }
  50. }
  51. int main() {
  52. ios::sync_with_stdio(false);
  53. cin.tie(0); cout.tie(0);
  54. cout << fixed << setprecision(20);
  55. #ifdef Local
  56. freopen("../input.in", "r", stdin);
  57. freopen("../output.out", "w", stdout);
  58. #endif
  59. int T; cin >> T;
  60. while(T--) run();
  61. return 0;
  62. }

D - The Moon

数学期望,就考虑几种情况就行,倒着来推,递推式详见代码:(因为有\(1.5\%\),所以是千分位)

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. using namespace std;
  7. typedef long long ll;
  8. typedef pair<int, int> pii;
  9. const int MAXN = 1e3+5;
  10. typedef double db;
  11. int t,p;
  12. db f[MAXN];
  13. db g(int x){
  14. return f[min(x,1000)];
  15. }
  16. int main() {
  17. scanf("%d",&t);
  18. for(int kase=1;kase<=t;kase++){
  19. scanf("%d",&p);
  20. f[1000] = 100.0/p;
  21. for(int i=995;i>=20;i-=5)
  22. f[i] = (p/100.0)*(i/1000.0) + (p/100.0)*((1000-i)/1000.0)*(1+g(i+20)) + (100-p)/100.0*(1+g(i+15));
  23. printf("Case %d: %.7f\n",kase,f[20]);
  24. }
  25. return 0;
  26. }

F - The Hermit

仔细分析一下题目条件就很好做了,每一个位置答案为\(a_i-2\)。

H - Lovers

题意:

一开始有\(n\)个空串\(s_1,s_2,\cdots,s_n\),然后执行\(m\)次操作,操作分为两种:

  • \(w\ l\ r\ d:\)给\(l\)到\(r\)位置上的所有子串两边加上\(d\),相当于\(s_i\)变为\(ds_id,l\leq i\leq r\);
  • \(q\ l\ r:\)询问\(\sum_{i=l}^r value*(s_i)(mod\ 10^9+7)\)。

思路:

硬核线段树。

考虑若对一个位置施加一次操作,结果为:

\[10\cdot d\cdot sum_2+10\cdot sum+d
\]

其中\(sum\)表示对应区间的答案和,\(sum_2\)表示对应区间的\(\sum 10^{len_i}\)。

三个的含义分别是头、中、尾部。

手玩一下,发现如果施加三次操作,结果将变为:

\[10^3\cdot sum_2\cdot [d_3d_2d_1]+10^3\cdot sum+[d_1d_2d_3]
\]

那么我们可以发现,我们维护懒标记时,可以单独维护\([d_1\cdots d_n],[d_n\cdots d_1],10^{len}\),这样懒标记的更新也很好更新,懒标记下传时直接对应乘起来即可。

其中\([d_1d_2\cdots d_n]\)表示\(value(d_1d_2\cdots d_n)\)。

一开始细节没有想清楚,感觉还是有点遗憾。

注意一下\(sum_2\)的更新。

详见代码:

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 all(x) (x).begin(), (x).end()
  7. // #define Local
  8. using namespace std;
  9. typedef long long ll;
  10. typedef pair<int, int> pii;
  11. const int N = 1e5 + 5, MOD = 1e9 + 7;
  12. int Case;
  13. int n, m;
  14. int sum[N << 2], sum2[N << 2];
  15. int llz[N << 2], rlz[N << 2], lenlz[N << 2];
  16. char s[10];
  17. void push_up(int o) {
  18. sum[o] = (sum[o << 1] + sum[o << 1|1]) % MOD;
  19. sum2[o] = (sum2[o << 1] + sum2[o << 1|1]) % MOD;
  20. }
  21. void upd(int son, int fa, int l, int r) {
  22. sum[son] = (1ll * lenlz[fa] * sum2[son] % MOD * llz[fa] % MOD +
  23. 1ll * lenlz[fa] * sum[son] % MOD +
  24. 1ll * rlz[fa] * (r - l + 1) % MOD) % MOD;
  25. sum2[son] = 1ll * lenlz[fa] * lenlz[fa] % MOD * sum2[son] % MOD;
  26. llz[son] = (1ll * llz[fa] * lenlz[son] % MOD + llz[son]) % MOD;
  27. rlz[son] = (1ll * rlz[son] * lenlz[fa] % MOD + rlz[fa]) % MOD;
  28. lenlz[son] = 1ll * lenlz[son] * lenlz[fa] % MOD;
  29. }
  30. void push_down(int o, int l, int r) {
  31. if(lenlz[o] > 1) {
  32. int mid = (l + r) >> 1;
  33. upd(o << 1, o, l, mid);
  34. upd(o << 1|1, o, mid + 1, r);
  35. lenlz[o] = 1;
  36. llz[o] = rlz[o] = 0;
  37. }
  38. }
  39. void build(int o, int l, int r) {
  40. llz[o] = rlz[o] = 0;
  41. lenlz[o] = 1;
  42. if(l == r) {
  43. sum[o] = 0; sum2[o] = 1;
  44. return;
  45. }
  46. int mid = (l + r) >> 1;
  47. build(o << 1, l, mid);
  48. build(o << 1|1, mid + 1, r);
  49. push_up(o);
  50. }
  51. void update(int o, int l, int r, int L, int R, int d) {
  52. if(L <= l && r <= R) {
  53. sum[o] = (1ll * sum[o] * 10 % MOD + 1ll * d * (r - l + 1) % MOD + 1ll * 10 * d * sum2[o] % MOD) % MOD;
  54. sum2[o] = 1ll * sum2[o] * 100 % MOD;
  55. llz[o] = (1ll * lenlz[o] * d % MOD + llz[o]) % MOD;
  56. rlz[o] = (1ll * rlz[o] * 10 + d) % MOD;
  57. lenlz[o] = 1ll * lenlz[o] * 10 % MOD;
  58. return;
  59. }
  60. push_down(o, l, r);
  61. int mid = (l + r) >> 1;
  62. if(L <= mid) update(o << 1, l, mid, L, R, d);
  63. if(R > mid) update(o << 1|1, mid + 1, r, L, R, d);
  64. push_up(o);
  65. }
  66. int query(int o, int l, int r, int L, int R) {
  67. if(L <= l && r <= R) {
  68. return sum[o];
  69. }
  70. push_down(o, l, r);
  71. int mid = (l + r) >> 1, res = 0;
  72. if(L <= mid) res = (res + query(o << 1, l, mid, L, R)) % MOD;
  73. if(R > mid) res = (res + query(o << 1|1, mid + 1, r, L, R)) % MOD;
  74. return res;
  75. }
  76. void run() {
  77. ++Case;
  78. cout << "Case " << Case << ":" << '\n';
  79. cin >> n >> m;
  80. build(1, 1, n);
  81. while(m--) {
  82. cin >> s;
  83. int l, r, d;
  84. if(s[0] == 'w') {
  85. cin >> l >> r >> d;
  86. update(1, 1, n, l, r, d);
  87. } else {
  88. cin >> l >> r;
  89. int ans = query(1, 1, n, l, r);
  90. cout << ans << '\n';
  91. }
  92. }
  93. }
  94. int main() {
  95. ios::sync_with_stdio(false);
  96. cin.tie(0); cout.tie(0);
  97. cout << fixed << setprecision(20);
  98. #ifdef Local
  99. freopen("../input.in", "r", stdin);
  100. freopen("../output.out", "w", stdout);
  101. #endif
  102. int T; cin >> T;
  103. while(T--) run();
  104. return 0;
  105. }

I - Strength

游戏王,憨憨贪心,分两种情况就行。

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 all(x) (x).begin(), (x).end()
  7. // #define Local
  8. using namespace std;
  9. typedef long long ll;
  10. typedef pair<int, int> pii;
  11. const int MAXN = 1e5+5;
  12. int t,n,m,a[MAXN],b[MAXN],c[MAXN];
  13. multiset<int> st;
  14. bool vis[MAXN];
  15. int main(){
  16. cin>>t;
  17. for(int kase=1;kase<=t;kase++){
  18. cin>>n>>m;
  19. for(int i=1;i<=n;i++)vis[i]=0;
  20. st.clear();
  21. for(int i=1;i<=n;i++)cin>>a[i];
  22. for(int i=1;i<=m;i++)cin>>b[i];
  23. int k=0;
  24. for(int i=1;i<=m;i++){
  25. int x;
  26. cin>>x;
  27. if(x==1)st.insert(b[i]);
  28. else c[++k] = b[i];
  29. }
  30. sort(a+1,a+1+n);
  31. sort(c+1,c+1+k);
  32. ll ans=0;
  33. for(int i=1;i<=n;i++){
  34. auto it = st.lower_bound(a[i]);
  35. if(*it == a[i]){
  36. st.erase(it);
  37. vis[i]=1;
  38. }else if(it!=st.begin()){
  39. it--;
  40. st.erase(it);
  41. vis[i]=1;
  42. }
  43. }
  44. ll sum = 0;
  45. if(st.size()==0){
  46. int j=1;
  47. for(int i=n;i>=1;i--){
  48. if(vis[i])continue;
  49. if(j<=k)sum += max(0,a[i] - c[j++]);
  50. else sum += a[i];
  51. }
  52. }
  53. ans = sum;
  54. int j=1;
  55. sum=0;
  56. for(int i=n;i>=1&&j<=k;i--){
  57. sum += max(0,a[i]-c[j++]);
  58. }
  59. ans=max(ans,sum);
  60. cout<<"Case "<<kase<<": "<<ans<<'\n';
  61. }
  62. return 0;
  63. }

2018CCPC吉林赛区的更多相关文章

  1. 2018CCPC吉林赛区 hdu6555~hdu6566

    2018CCPC吉林赛区(重现赛)- 感谢北华大学 A 基础数论. #include<bits/stdc++.h> using namespace std; typedef long lo ...

  2. [2018CCPC吉林赛区(重现赛)- 感谢北华大学] 补题记录 躁起来

    1007 High Priestess 埃及分数 1008 Lovers 线段树维护取膜意义下的区间s和. 每个区间保存前缀lazy和后缀lazy. #include <iostream> ...

  3. 2018CCPC吉林赛区(重现赛)

    http://acm.hdu.edu.cn/contests/contest_show.php?cid=867 A题,直接分块,不知道正解是什么. #include<bits/stdc++.h& ...

  4. 2018CCPC吉林赛区 | 部分题解 (HDU6555 HDU6556 HDU6559 HDU6561)

    // 杭电上的重现赛:http://acm.hdu.edu.cn/contests/contest_show.php?cid=867 // 杭电6555~6566可交题 A - The Fool 题目 ...

  5. 2018CCPC吉林赛区(重现赛)部分题解

    The Fool 题目链接 Problem Description The Fool is numbered 0 – the number of unlimited potential –and th ...

  6. 2018CCPC 吉林现场赛 赛后总结

    一直以来都没有比赛完写总结的习惯,导致前面几次比赛都没有写过总结. 这是我写的第一场总结把,有时间有想法还记得细节的话再把前面几次比赛的总结给补上把. 热身赛: 热身赛的时候,写的比较急想着快点做出题 ...

  7. HDU 6556 (2018CCPC吉林 B题)

    ### HDU 6556 题目链接 ### 题目大意: 给你四个国家的时区,告诉你 A 国家的时间,让你输出这时候在 B 国家的时间,还需要输出对于 A 国家来说这是 昨天.今天 还是 明天. 分析前 ...

  8. 2018ccpc吉林 E:THE TOWER——数形结合

    题目 链接 给你一个圆锥(位于坐标原点,告诉你高h 和底面半径 r),和一个点(x,y,z)并告诉你这个点的速度, 让你求点和圆锥相撞的最小时间(保证一定相撞) 分析 易知,将直线的参数方程与圆锥曲面 ...

  9. HDU 6562 lovers 2018CCPC吉林H(线段树)

    题意: 初始n个空串,m个操作: 1.给[l,r]的所有字符串头尾加一个‘d’,将原字符串x变为dxd 2.求[l,r]所有字符串代表的数字之和mod 1e9+7 思路: 据说是硬核线段树.. 对于线 ...

随机推荐

  1. day 27-1 反射、内置方法

    反射 反射:通过字符串来映射到对象的属性 class People(): def __init__(self, name, age): self.name = name self.age = age ...

  2. How to: Use the Entity Framework Code First in XAF 如何:在 XAF 中使用EF CodeFirst

    This topic demonstrates how to create a simple XAF application with a business model in a DbContext ...

  3. 【iOS13问题】修改状态栏的颜色(亲测,有效)

    - (UIStatusBarStyle)preferredStatusBarStyle { if (@available(iOS 13.0, *)) { return UIStatusBarStyle ...

  4. LeetCode刷题191218

    好多天没有更新了,今天有空,刷一道. 算法第5题 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad"输出: ...

  5. Vue-cli脚手架 安装 并创建项目--命令

    检查是否有 node - v 安装Vue-cli npm install -g vue-cli 安装好后,执行 vue list可以看到很多实用的模板,我这里实用的webpack 初始化模板 vue ...

  6. 一次在CentOS系统单用户模式下使用passwd命令破密失败的案例

    某次遇到需要进入系统的单用户模式进行破密操作,结果却显示如下: 根据提示:Permission denied(缺少权限) 此时查看/usr/bin/passwd 权限: 正常情况下的权限应该是如下: ...

  7. Mac下搭建Cocos2d-x-3.2的开发环境

    配置:OS X 10.9.4 + Xcode 6.0 + Cocos2d-x-3.2 摘要:本文目标为在Xcode成功运行HelloWorld程序. 一.下载必要项 1.从官网下载Cocos2d-x- ...

  8. docker Dockerfile里使用的命令说明

    一,dockerfile格式 注释# 指令 参数 指令不区分大小写,但是推荐全部大写指令. 指令从上到下顺序被执行 第一个指令必须是[FROM],指示出要使用的基础镜像. 执行docker file时 ...

  9. asp开发类型判段

    Asp的东西有许多,asp的类型便是其中之一,如同Asp的数据类型只需一个那便是"variant ". 它是一种特别的数据类型可以依据它的运用标明许多不同品种的信息(cnhfjj) ...

  10. Ubuntu18.04 设置开机进入命令行模式

    首先来了解下启动级别(Runlevel): 指 Unix 或 类 Unix 操作系统下不同的运行模式,运行级别通常分为 7 级: 运行级别 0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启 ...