比赛传送门:CF #1110

比赛记录:点我

涨了挺多分,希望下次还能涨。


【A】Parity

题意简述:

问 \(k\) 位 \(b\) 进制数 \(\overline{a_1a_2\cdots a_k}\) 的奇偶性。

题解:

若 \(b\) 是偶数,则答案等于 \(a_k\) 的奇偶性。

若 \(b\) 是奇数,则答案等于 \(\sum_{i=1}^{k}a_i\) 的奇偶性。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define F(i,a,b) for(int i=a;i<=(b);++i)
  4. #define MN 100005
  5. int b,k;
  6. int a[MN];
  7. int main(){
  8. scanf("%d%d",&b,&k);
  9. F(i,1,k)scanf("%d",a+i);
  10. if(b%2==0)puts(a[k]%2==0?"even":"odd");
  11. else{
  12. int s=0;
  13. F(i,1,k)s^=a[i]&1;
  14. puts(s?"odd":"even");
  15. }
  16. return 0;
  17. }

【B】Tape

题意简述:

有 \(n\) 个线段,第 \(i\) 个覆盖了数轴上的区间 \([b_i,b_i+1]\),保证 \(b_1<b_2<\cdots<b_n\le m\)。

你需要用不超过 \(k\) 个区间覆盖所有线段,求使用的区间总长度最小值。

题解:

假设一开始用 \(n\) 个长度为 \(1\) 的区间覆盖了所有线段。

每次可以选择相邻的两个区间,把它们合并,长度增加它们之间的距离,区间个数减少 \(1\)。

那么我们令答案等于 \(n\),把 \(\{b_2-b_1-1,b_3-b_2-1,\ldots,b_n-b_{n-1}-1\}\) 从小到大排序,将前 \(k\) 小加入答案即可。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define F(i,a,b) for(int i=a;i<=(b);++i)
  4. #define MN 100005
  5. int n,m,k;
  6. int a[MN],b[MN];
  7. int main(){
  8. scanf("%d%d%d",&n,&m,&k);
  9. F(i,1,n)scanf("%d",a+i);
  10. F(i,1,n-1)b[i]=a[i+1]-a[i]-1;
  11. sort(b+1,b+n);
  12. long long s=n;
  13. F(i,1,n-k)s+=b[i];
  14. printf("%lld\n",s);
  15. return 0;
  16. }

【C】Meaningless Operations

题意简述:

定义函数 \(f(a)=\max_{0<b<a}\gcd(a\oplus b,a\>\&\>b)\)。

\(q\) 次询问,每次给定 \(a_i\),询问 \(f(a_i)\) 的值。

\(1\le q\le 10^3\),\(2\le a_i\le 2^{25}-1\)。

题解:

如果 \(a\ne 2^i-1\),假设 \(a\) 有 \(k\) 位,令 \(b=2^k-1-a\),则 \(a\oplus b=2^k-1\),\(a\>\&\>b=0\),\(\gcd(2^k-1,0)=2^k-1\)。

容易证明 \(f(a)\le 2^k-1\),所以这样是最大的。

如果 \(a=2^i-1\),此时对于任意的 \(b\),有 \(a\oplus b=a-b\),\(a\>\&\>b=b\),则 \(f(a)=\max_{0<b<a}\gcd(b,a-b)\)。

所以答案一定是 \(a\) 的一个不等于自身的因数。假设 \(a\) 最大不等于自身的因数为 \(d\),取 \(b=d\) 即可得到最大的答案。

对 \(a\) 用 \(O(\sqrt{a})\) 的时间找到最小的质因子即可。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define F(i,a,b) for(int i=a;i<=(b);++i)
  4. int q,a;
  5. int main(){
  6. scanf("%d",&q);
  7. F(i,1,q){
  8. scanf("%d",&a);
  9. if((a+1)&a){
  10. int x=1;
  11. while(x<=a)x<<=1;
  12. printf("%d\n",x-1);
  13. }
  14. else{
  15. int y=0;
  16. for(int x=2;x*x<=a;++x)
  17. if(a%x==0){y=x;break;}
  18. if(!y)puts("1");
  19. else printf("%d\n",a/y);
  20. }
  21. }
  22. return 0;
  23. }

【D】Jongmah

题意简述:

你有 \(n\) 个正整数 \(a_i\le m\),每次可以消去 \(3\) 个相等的数或者 \(3\) 个连续的数。问最多可以消几次。

题解:

对于消去 \(3\) 个连续的数\((a-1,a,a+1)\),相同的消除不会超过 \(3\) 次,因为如果超过 \(3\) 次,可以替换为消除 \(3\) 次相等的数。

记录 \(\mathrm{b}[i]\) 为 \(i\) 的出现次数。

考虑 \(\mathrm{dp}\),记 \(\mathrm{f}[i][j][k]\) 表示对于小于等于 \(i\) 的数,进行了 \(j\) 次 \((i-1,i,i+1)\) 的消除,进行了 \(k\) 次 \((i,i+1,i+2)\) 的消除最多能消除几次。

这里不考虑 \(i+1\) 和 \(i+2\) 出现的次数。

转移比较显然,在保证 \(b[i]\ge j+k+l\) 的情况下,有 \(\mathrm{f}[i][k][l]=\mathrm{f}[i-1][j][k]+l+\lfloor\frac{b[i]-j-k-l}{3}\rfloor\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define MN 1000005
  4. int N, M;
  5. int b[MN], f[MN][3][3];
  6. int main(){
  7. scanf("%d%d", &N, &M);
  8. for (int i = 1, x; i <= N; ++i) scanf("%d", &x), ++b[x];
  9. for (int i = 1; i <= M; ++i)
  10. for (int j = 0; j < 3; ++j)
  11. for (int k = 0; k < 3; ++k)
  12. for (int l = 0; l < 3; ++l)
  13. if (b[i] < j + k + l) continue ;
  14. else f[i][k][l] = max(f[i][k][l], f[i - 1][j][k] + (b[i] - j - k - l) / 3 + l);
  15. printf("%d\n", f[M][0][0]);
  16. return 0;
  17. }

【E】Magic Stones

题意简述:

一个长度为 \(n\) 的序列 \(a_1,a_2,\ldots,a_n\)。每次可以对第 \(i(1<i<n)\) 位进行操作:\(c_i\leftarrow c_{i+1}+c_{i-1}-c_i\)。

问是否可以变成另一个序列 \(b_1,b_2,\ldots,b_n\)。

题解:

首先必须有 \(a_1=b_1\) 和 \(a_n=b_n\)。

考虑原序列的差分,分析一次操作对其造成的影响:

假设 \(c_i=a_{i+1}-a_i\),则对第 \(i\) 位的操作会让 \(c_{i-1}\) 与 \(c_i\) 交换。

则显然 \(c_i\) 形成的多重集在操作下是不会改变的,又因为只依靠交换相邻两位就可以把序列任意重排,所以只要判断原序列和最终序列的差分是否本质相同即可。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define F(i,a,b) for(int i=a;i<=(b);++i)
  4. #define MN 100005
  5. int n,m,q,k;
  6. int a[MN],b[MN],c[MN],d[MN];
  7. int main(){
  8. scanf("%d",&n);
  9. F(i,1,n)scanf("%d",a+i);
  10. F(i,1,n)scanf("%d",b+i);
  11. if(a[1]!=b[1]||a[n]!=b[n])return puts("No"),0;
  12. F(i,1,n-1)c[i]=a[i+1]-a[i];
  13. F(i,1,n-1)d[i]=b[i+1]-b[i];
  14. sort(c+1,c+n);sort(d+1,d+n);
  15. F(i,1,n-1)if(c[i]!=d[i])return puts("No"),0;
  16. puts("Yes");
  17. return 0;
  18. }

【F】Nearest Leaf

题意简述:

给定一棵 \(n\) 个点的以 \(1\) 号点为根的树,有边权,保证 \(1\) 号点不是叶子。

一个性质:这棵树从 \(1\) 开始 \(\mathrm{DFS}\),遍历到一个点之后按照编号递增的顺序遍历它的儿子,得到的 \(\mathrm{DFS}\) 序恰好是 \(1\) 到 \(n\)。

\(q\) 次询问,每次问 \(v_i\) 号点到编号在 \([l_i,r_i]\) 中的叶子的最小距离。

题解:

输入的树只有给定每个节点的父亲,这时可以通过一个栈求出每个点的子树中的最大 \(\mathrm{DFS}\) 序。

考虑对于结点 \(u\),用支持区间加,区间查 \(\min\) 的线段树维护 \(u\) 到每个叶子的距离,则对于 \(v_i=u\) 的询问可以直接查询。

发现可以离线,我们把询问按照 \(v_i\) 排序,模拟一个 \(\mathrm{DFS}\) 的过程。

当前遍历到的结点沿着一条边改变时,就在线段树上修改全局权值加上 \(w_i\),子树权值减去 \(-2w_i\)。

  1. #include <cstdio>
  2. #include <vector>
  3. #include <algorithm>
  4. typedef long long LL;
  5. typedef std::pair<int, int> pii;
  6. const LL INF = 0x3f3f3f3f3f3f3f3f;
  7. const int MN = 500005;
  8. int N, Q;
  9. int faz[MN], d[MN], rdf[MN], stk[MN], t;
  10. LL w[MN], dis[MN];
  11. std::vector<int> c[MN], q[MN];
  12. int l[MN], r[MN];
  13. LL Ans[MN];
  14. const int MS = 1 << 20;
  15. #define li (i << 1)
  16. #define ri (i << 1 | 1)
  17. #define mid ((l + r) >> 1)
  18. #define ls li, l, mid
  19. #define rs ri, mid + 1, r
  20. LL mn[MS], tg[MS];
  21. inline void P(int i, LL v) { mn[i] += v; tg[i] += v; }
  22. inline void pd(int i) { if (tg[i]) P(li, tg[i]), P(ri, tg[i]), tg[i] = 0; }
  23. void Mdf(int i, int l, int r, int a, int b, LL v) {
  24. if (r < a || b < l) return ;
  25. if (a <= l && r <= b) return P(i, v);
  26. pd(i), Mdf(ls, a, b, v), Mdf(rs, a, b, v);
  27. mn[i] = std::min(mn[li], mn[ri]);
  28. }
  29. LL Qur(int i, int l, int r, int a, int b) {
  30. if (r < a || b < l) return INF;
  31. if (a <= l && r <= b) return mn[i];
  32. pd(i); return std::min(Qur(ls, a, b), Qur(rs, a, b));
  33. }
  34. void DFS(int u) {
  35. Mdf(1, 1, N, 1, N, w[u]);
  36. Mdf(1, 1, N, u, rdf[u], -2 * w[u]);
  37. for (int i : q[u]) Ans[i] = Qur(1, 1, N, l[i], r[i]);
  38. for (int i : c[u]) DFS(i);
  39. Mdf(1, 1, N, 1, N, -w[u]);
  40. Mdf(1, 1, N, u, rdf[u], 2 * w[u]);
  41. }
  42. int main() {
  43. scanf("%d%d", &N, &Q);
  44. stk[t = 1] = 1;
  45. for (int i = 2; i <= N; ++i) {
  46. scanf("%d%lld", &faz[i], &w[i]);
  47. c[faz[i]].push_back(i);
  48. ++d[faz[i]], ++d[i];
  49. dis[i] = dis[faz[i]] + w[i];
  50. while (faz[i] != stk[t]) rdf[stk[t--]] = i - 1;
  51. stk[++t] = i;
  52. }
  53. while (t) rdf[stk[t--]] = N;
  54. for (int i = 1; i <= N; ++i) {
  55. if (d[i] == 1) Mdf(1, 1, N, i, i, dis[i]);
  56. else Mdf(1, 1, N, i, i, INF);
  57. }
  58. for (int i = 1, u; i <= Q; ++i) {
  59. scanf("%d%d%d", &u, &l[i], &r[i]);
  60. q[u].push_back(i);
  61. }
  62. DFS(1);
  63. for (int i = 1; i <= Q; ++i) printf("%lld\n", Ans[i]);
  64. return 0;
  65. }

CodeForces Contest #1110: Global Round 1的更多相关文章

  1. Codeforces Global Round 1 (A-E题解)

    Codeforces Global Round 1 题目链接:https://codeforces.com/contest/1110 A. Parity 题意: 给出{ak},b,k,判断a1*b^( ...

  2. Codeforces Global Round 2 题解

    Codeforces Global Round 2 题目链接:https://codeforces.com/contest/1119 A. Ilya and a Colorful Walk 题意: 给 ...

  3. CodeForces Global Round 1

    CodeForces Global Round 1 CF新的比赛呢(虽然没啥区别)!这种报名的人多的比赛涨分是真的快.... 所以就写下题解吧. A. Parity 太简单了,随便模拟一下就完了. B ...

  4. Codeforces Global Round 1 - D. Jongmah(动态规划)

    Problem   Codeforces Global Round 1 - D. Jongmah Time Limit: 3000 mSec Problem Description Input Out ...

  5. Codeforces Global Round 3

    Codeforces Global Round 3 A. Another One Bites The Dust 有若干个a,有若干个b,有若干个ab.你现在要把这些串拼成一个串,使得任意两个相邻的位置 ...

  6. Codeforces Global Round 1 (CF1110) (未完结,只有 A-F)

    Codeforces Global Round 1 (CF1110) 继续补题.因为看见同学打了这场,而且涨分还不错,所以觉得这套题目可能会比较有意思. 因为下午要开学了,所以恐怕暂时不能把这套题目补 ...

  7. 【手抖康复训练1 】Codeforces Global Round 6

    [手抖康复训练1 ]Codeforces Global Round 6 总结:不想复习随意打的一场,比赛开始就是熟悉的N分钟进不去时间,2333,太久没写题的后果就是:A 题手抖过不了样例 B题秒出思 ...

  8. Codeforces Global Round 11 个人题解(B题)

    Codeforces Global Round 11 1427A. Avoiding Zero 题目链接:click here 待补 1427B. Chess Cheater 题目链接:click h ...

  9. [cf contest 893(edu round 33)] F - Subtree Minimum Query

    [cf contest 893(edu round 33)] F - Subtree Minimum Query time limit per test 6 seconds memory limit ...

随机推荐

  1. Java运算符、switch、数组、排序

    1.Java的运算符,分为四类:算数运算符.关系运算符.逻辑运算符.位运算符 运算符例子:22.25(十进制转化为二进制,8421码)0010 0010 (22)0010 0101 (25) 位运算符 ...

  2. squid介绍和作用

    介绍 squid服务程序是一款在Unix系统中最为流行的高性能代理服务软件,通常会被当作网站的前置缓存服务,用于替代用户向网站服务器请求页面数据并进行缓存,通俗来讲,Squid服务程序会接收用户的请求 ...

  3. 深入理解ajax系列第八篇——表单提交

    前面的话 在以前,网站的用户与后端交互的主要方式是通过HTML表单的使用.表单的引入在1993年,由于其简单性和易用性,直到电子商务出现之前一直保持着重要位置.理解表单提交,对于更深入地理解ajax是 ...

  4. java 堆和栈二

    1.数组 整数默认初始化值0 浮点数默认初始化值0.0 布尔类型默认初始化值false 字符类型默认初始化值\u0000 [I@7852e922 [有几个代表是几维数组 I代表是Int类型 @固定格式 ...

  5. 一本通1632【 例 2】[NOIP2012]同余方程

    1632:[ 例 2][NOIP2012]同余方程 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 求关于 x 的同余方程 ax≡1(mod b) 的最小正整 ...

  6. js new关键字

    实现new 关键字只需4步 1. 声明一个对象: 2. 把这个对象的__proto__ 指向构造函数的 prototype; 3. 以构造函数为上下文执行这个对象: 4. 返回这个对象. 简洁的代码示 ...

  7. Java之Set的使用场景

    2.Set使用场景 API介绍: java.util.Set接口和java.util.List接口一样,同样继承自Collection接口, 它与Collection接口中的方法基本一致,并没有对Co ...

  8. Again Prime? No Time. UVA - 10780(质因子分解)

    m^k就是让m的每个质因子个数都增加了k倍 求m的质因子 在n!中增加了多少倍就好了,因为m^k 表示每一个质因子增加相同的倍数k  所以我们需要找到增加倍数最小的那个..短板效应  其它质因子多增加 ...

  9. bzoj 1050 [HAOI2006]旅行comf (并查集)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1050 思路: 先将每条边的权值排个序优先小的,然后从小到大枚举每一条边,将其存到并查集 ...

  10. Lua 调试库

    Lua 调试库 http://blog.csdn.net/vermilliontear/article/details/50851045 http://blog.csdn.net/vermillion ...