ccf-csp201809题解

标签(空格分隔): ccf题解



1. 201809-1 卖菜

题目描述

试题编号: 201809-1

试题名称: 卖菜

时间限制: 1.0s

内存限制: 256.0MB

问题描述

  在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜。

  第一天,每个商店都自己定了一个价格。店主们希望自己的菜价和其他商店的一致,第二天,每一家商店都会根据他自己和相邻商店的价格调整自己的价格。具体的,每家商店都会将第二天的菜价设置为自己和相邻商店第一天菜价的平均值(用去尾法取整)。

  注意,编号为1的商店只有一个相邻的商店2,编号为n的商店只有一个相邻的商店n-1,其他编号为i的商店有两个相邻的商店i-1和i+1。

  给定第一天各个商店的菜价,请计算第二天每个商店的菜价。

输入格式

  输入的第一行包含一个整数n,表示商店的数量。

  第二行包含n个整数,依次表示每个商店第一天的菜价。

输出格式

  输出一行,包含n个正整数,依次表示每个商店第二天的菜价。

样例输入

8

4 1 3 1 6 5 17 9

样例输出

2 2 1 3 4 9 10 13

数据规模和约定

  对于所有评测用例,2 ≤ n ≤ 1000,第一天每个商店的菜价为不超过10000的正整数。

解析

依题意,先将输入的数据用数组存下来(也可以使用在线做法),然后用\(O(n)\)的复杂度跑一遍,依次输出相邻三个数的平均值。

通过代码

  1. //1591298 <13100928923> <王恪楠> 卖菜 11-09 21:28 409B C0X 正确 100 15ms 532.0KB
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. const int MAXN = 1e3 + 50;
  5. int a[MAXN];
  6. int main()
  7. {
  8. int n;
  9. scanf("%d", &n);
  10. for(int i = 1; i <= n; i ++)
  11. scanf("%d", &a[i]);
  12. for(int i = 1; i <= n; i ++){
  13. int t = (a[i - 1] + a[i] + a[i + 1]);
  14. if(i == 1 || i == n) //第一个数和最后一个数的相邻数只有一个,所以求平均数只除以2.
  15. printf("%d ", t / 2);
  16. else
  17. printf("%d ", t / 3);
  18. }
  19. return 0;
  20. }

2. 201809-2 买菜

题目描述

试题编号: 201809-2

试题名称: 买菜

时间限制: 1.0s

内存限制: 256.0MB

问题描述

  小H和小W来到了一条街上,两人分开买菜,他们买菜的过程可以描述为,去店里买一些菜然后去旁边的一个广场把菜装上车,两人都要买n种菜,所以也都要装n次车。具体的,对于小H来说有n个不相交的时间段[a1,b1],[a2,b2]...[an,bn]在装车,对于小W来说有n个不相交的时间段[c1,d1],[c2,d2]...[cn,dn]在装车。其中,一个时间段[s, t]表示的是从时刻s到时刻t这段时间,时长为t-s。

  由于他们是好朋友,他们都在广场上装车的时候会聊天,他们想知道他们可以聊多长时间。

输入格式

  输入的第一行包含一个正整数n,表示时间段的数量。

  接下来n行每行两个数ai,bi,描述小H的各个装车的时间段。

  接下来n行每行两个数ci,di,描述小W的各个装车的时间段。

输出格式

  输出一行,一个正整数,表示两人可以聊多长时间。

样例输入

4

1 3

5 6

9 13

14 15

2 4

5 7

10 11

13 14

样例输出

3

数据规模和约定

  对于所有的评测用例,1 ≤ n ≤ 2000, ai < bi < ai+1,ci < di < ci+1,对于所有的i(1 ≤ i ≤ n)有,1 ≤ ai, bi, ci, di ≤ 1000000。

解析

因为两个人自己装车的区间不会重合,那么我们就将两个人的装车区间打上标记,然后所有被打过两次标记的区间就都是所求。可以用\(vis[1\cdots m]\)数组记录区间打标记情况。

因为输入所给的\(a_i,b_i(c_i, d_i)\)分别是区间的左右端点,而不是区间的编号,所以我们在进行标记的时候要注意标记区间而不是区间端点。具体做法就是对于\([l, r)\)内的点进行标记(\(l\)区间左端点,\(r\)区间右端点)。



蓝色数字为区间端点序号,黄色数字为区间编号

通过代码

  1. //1591321 <13100928923> <王恪楠> 买菜 11-09 21:42 473B C0X 正确 100 15ms 4.335MB
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. const int MAXN = 1e6 + 50;
  5. int vis[MAXN];
  6. int main()
  7. {
  8. int n, m = 0;
  9. scanf("%d", &n);
  10. for(int i = 1; i <= n + n; i ++){
  11. int l, r;
  12. scanf("%d%d", &l, &r);
  13. m = max(m, r);
  14. for(int j = l; j < r; j ++) //将每个区间长度[l,r)打上标记.
  15. vis[j] ++;
  16. }
  17. int ans = 0;
  18. for(int i = 1; i <= m; i ++)
  19. if(vis[i] == 2) //如果一个单位长度被打过两次标记,说明这个单位长度是两人共同装车的时间.
  20. ans ++;
  21. printf("%d", ans);
  22. return 0;
  23. }

3.201809-3 元素选择器

题目描述

试题编号: 201809-3

试题名称: 元素选择器

时间限制: 1.0s

内存限制: 256.0MB







解析

大致题意:

我们想要对一个树形(or森林)的字符串结构体进行查找操作。

输入:

第一行为n和m。分别代表输入的字符串个数,和查询个数。

下面的n行每行为一个字符串。给出n个结构体。每行的字符串都以"."为起始且点的个数只能为偶数个(可以为0个),代表这一结构体的缩进等级。(缩进等级大的结构体的前缀为与其最近的等级减2的结构体。)之后的字符串为该结构体的标签(不区分大小写,可统一化为小写),之后如果有"#",则"#"之后的字符串为该结构体的id,id区分大小写,且唯一。

下面的m行每行为一个字符串。给出m个查询操作。

1.形如"tag"的字符串,查询标签为"tag"的结构体的序号。

2.形如"#id"的字符串,查询id为"id"的结构体的序号。

3.形如"tag tag #id #id ..."的字符串,查询从左至右,是否每前一个结构体为后一个结构体的前缀,如果满足,则记录最后一个结构体的序号。遇到"tag"则是对比结构体标签,遇到"#id"对比结构体id。

输出:

将每一个查询得到的序号从小到大输出,然后输出换行。

我们可以用一个结构体来储存每一行的缩进等级(int),标签(string),id(string)。

对于查询1和查询2较为简单,因为数据规模较小,我们可以简单的\(O(n)\)实现。

对于查询3,我们需要用一个栈将所要查询的字符串先储存下来,然后找到栈顶的结构体,再用它的前缀不断递归一一和栈中元素对比。

通过代码

  1. //1599261 <13100928923> <王恪楠> 元素选择器 11-14 21:00 3.233KB C0X 正确 100 15ms 632.0KB
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. struct Node
  5. {
  6. int fa;
  7. string tag, id; //fa是结构体的父亲节点的序号,tag是标签,id是id值.
  8. }a[500];
  9. int last[500], top; //last是存储每一个缩进等级的最近节点序号,比它小一级(值-2)的节点都以此节点为父亲节点.
  10. string s0, s[500]; //用s[1...n]和top模拟栈.后代选择器时使用.
  11. vector<int> ans; //用以记录答案的向量.
  12. ostream &operator << (ostream &out, const Node &i) //重载<<,输出结构体.(测试程序时用)
  13. {
  14. cout << i.tag << " " << i.id << " " << i.fa;
  15. return out;
  16. }
  17. bool cmp(int i, string ss) //比较函数.如果字符串带#则和id比较.如果字符串不带#则和tag比较,和tag比较时00不区分大小写.
  18. {
  19. string str;
  20. if(ss[0] == '#'){
  21. for(int j = 1; j < ss.length(); j ++)
  22. str += ss[j];
  23. return a[i].id == str;
  24. }
  25. transform(ss.begin(), ss.end(), ss.begin(), ::tolower); //将ss都转变为小写,再和tag作比较.
  26. return a[i].tag == ss;
  27. }
  28. int getfa(int i) //后代选择器.不断地寻找节点的父亲节点,和栈顶字符串作比较.如果能使栈为空,说明后代选择器的所有祖先字符串都能被找到.
  29. {
  30. if(i == 0){ //当找到第一缩进等级,节点没有父亲节点时,就要返回!top的值了.
  31. return !top;
  32. }
  33. if(top == 0){
  34. return 1;
  35. }
  36. if(cmp(i, s[top - 1])){
  37. top --;
  38. }
  39. return getfa(a[i].fa);
  40. }
  41. void print()
  42. {
  43. printf("%d", ans.size());
  44. for(int i = 0; i < ans.size(); i ++)
  45. printf(" %d", ans[i]);
  46. printf("\n");
  47. return ;
  48. }
  49. void split(string ss) //字符串分割,以空格为分割符.分割后入栈.
  50. {
  51. string str;
  52. for(int i = 0; i < ss.length(); i ++){
  53. if(ss[i] == ' '){
  54. s[top ++] = str;
  55. str.clear();
  56. }
  57. else
  58. str += ss[i];
  59. }
  60. s[top ++] = str;
  61. return;
  62. }
  63. int main()
  64. {
  65. int n, m;
  66. scanf("%d%d", &n, &m);getchar();
  67. for(int i = 1; i <= n; i ++){
  68. getline(cin, s0); //getline()可以整行输入字符串,而不是遇到空格就停止.
  69. int level, pos = 0, flag = 1;
  70. for(int j = 0; j < s0.length(); j ++){
  71. if(s0[j] != '.' && flag){ //记录缩进等级.
  72. level = j;
  73. flag = 0;
  74. }
  75. if(s0[j] == '#') //判断是否有id.
  76. pos = j;
  77. }
  78. last[level] = i; //这个缩进等级的最近一个序号更新为这个节点的序号.
  79. if(level == 0)
  80. a[i].fa = 0; //如果是第零级,那么它就没有祖先节点,就为0.
  81. else
  82. a[i].fa = last[level - 2]; //否则最近的上一缩进等级的序号就是该节点的祖先.
  83. string tag;
  84. for(int j = level; j < s0.length() && s0[j] != ' '; j ++)
  85. tag += s0[j];
  86. transform(tag.begin(), tag.end(), tag.begin(), ::tolower);
  87. a[i].tag = tag; //存下标签tag(注意tag不区分大小写,那么就统一用小写字母存).
  88. if(pos){
  89. string id;
  90. for(int j = pos + 1; j < s0.length(); j ++) //存下id.
  91. id += s0[j];
  92. a[i].id = id;
  93. }
  94. }
  95. while(m --){
  96. getline(cin, s0);
  97. ans.clear();
  98. top = 0;
  99. split(s0); //分割字符串.如果只有一个字符串,也没有影响.
  100. string t = s[top - 1];
  101. top --;
  102. int mm = top;
  103. for(int i = 1; i <= n; i ++)
  104. if(cmp(i, t)){ //将各个节点和栈顶字符串作比较.
  105. top = mm; //每次查找祖先时,将栈顶指针还原,即将栈还原.
  106. if(getfa(a[i].fa))
  107. ans.push_back(i);
  108. }
  109. print();
  110. }
  111. return 0;
  112. }

4.201809-4 再卖菜

题目描述

试题编号: 201809-4

试题名称: 再卖菜

时间限制: 1.0s

内存限制: 256.0MB

问题描述

  在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜。

  第一天,每个商店都自己定了一个正整数的价格。店主们希望自己的菜价和其他商店的一致,第二天,每一家商店都会根据他自己和相邻商店的价格调整自己的价格。具体的,每家商店都会将第二天的菜价设置为自己和相邻商店第一天菜价的平均值(用去尾法取整)。

  注意,编号为1的商店只有一个相邻的商店2,编号为n的商店只有一个相邻的商店n-1,其他编号为i的商店有两个相邻的商店i-1和i+1。

  给定第二天各个商店的菜价,可能存在不同的符合要求的第一天的菜价,请找到符合要求的第一天菜价中字典序最小的一种。

  字典序大小的定义:对于两个不同的价格序列(a1, a2, ..., an)和(b1, b2, b3, ..., bn),若存在i (i>=1), 使得ai<bi,且对于所有j<i,aj=bj,则认为第一个序列的字典序小于第二个序列。

输入格式

  输入的第一行包含一个整数n,表示商店的数量。

  第二行包含n个正整数,依次表示每个商店第二天的菜价。

输出格式

  输出一行,包含n个正整数,依次表示每个商店第一天的菜价。

样例输入

8

2 2 1 3 4 9 10 13

样例输出

2 2 2 1 6 5 16 10

数据规模和约定

  对于30%的评测用例,2<=n<=5,第二天每个商店的菜价为不超过10的正整数;

  对于60%的评测用例,2<=n<=20,第二天每个商店的菜价为不超过100的正整数;

  对于所有评测用例,2<=n<=300,第二天每个商店的菜价为不超过100的正整数。

  请注意,以上都是给的第二天菜价的范围,第一天菜价可能会超过此范围。

解析

本题所考察的知识点是差分约束系统。在白书最短路算法的最后一道例题讲对差分约束系统有所讲解。

CSDN 差分约束算法总结 by Dust_Heart

本题如何建图?

设第\(i\)个菜店第一天的菜价为\(b[i]\,\),第二天的菜价(即第一天相邻店铺菜价的平均值)为\(a[i]\),\(\sum_{i=0}^{n}b[i] = d[n]\)(即\(b[i]\)的前缀和为\(d[i]\))。

  • 因为差分约束系统不等式一侧只能有两个变量,所以\(d[i]\)为前缀和,即可一般地,把\(a[i]\)相邻的三个数\(b[i-1],b[i],b[i+1]\)的平均值不等式表达为\(3 * a[i] \leq d[i + 1] - d[i - 2] \leq 3*a[i] + 2\).

  • 本题是希望找到最小的\(b[i]\),即是想找到最小的\(d[i] - d[i - 1]\),对应于差分约束系统需要建立形如\(v - u \geq w\)的不等式组,同时建立一条起点为\(u\),终点为\(v\),权值为\(w\)的边,然后找出不等式组的最大值。

  • 当\(i\in[2, n - 1]\)时,$$3 * a[i] \leq d[i + 1] - d[i - 2] \leq 3*a[i] + 2 \Rightarrow

    \begin{cases}

    d[i+1] - d[i - 2] \geq 3 * a[i], \

    d[i - 2] - d[i + 1] \geq -3 * a[i] - 2.

    \end{cases}$$

  • 因为首尾只有两个店铺和它们相邻,所以当\(i \in \{1, n\}\,\)时,$$

    \begin{cases}

    d[2] - d[0] \geq 2 * a[1], \

    d[0] - d[2] \geq -2 * a[1] - 1;

    \end{cases};;

    \begin{cases}

    d[n] - d[n - 2] \geq 2 * a[n], \

    d[n - 2] - d[n] \geq -2 * a[n] - 1.

    \end{cases}$$

  • 将形如不等式\(v - u \geq w\)添加一条\(u \to v\)的权值为\(w\)的边。

当我们通过上述方法完成建图之后,就只要虚拟一个起始源点用dijsktra跑一遍找出单源最长路即可。

通过代码

  1. //1613829 <13100928923> <王恪楠> 再卖菜 11-21 21:22 1.678KB C0X 正确 100 15ms 576.0KB
  2. #include <bits/stdc++.h>
  3. #define to first
  4. #define coast second
  5. using namespace std;
  6. const int MAXN = 5e2;
  7. typedef pair<int, int> P;
  8. int a[MAXN], s[MAXN], d[MAXN], n;
  9. vector<P> G[MAXN];
  10. void add_edge(int u, int v, int w)
  11. {
  12. G[u].push_back(P(v, w));
  13. return;
  14. }
  15. void dijsktra() //用dijsktra算法求最长路,把最短路的写法反过来写.
  16. {
  17. priority_queue<P> q;
  18. d[0] = 0;
  19. q.push(P(0, 0));
  20. while(!q.empty()){
  21. P p = q.top();
  22. q.pop();
  23. int v = p.second;
  24. if(d[v] > p.first) continue;
  25. for(int i = 0; i < G[v].size(); i ++){
  26. P e = G[v][i];
  27. if(d[e.to] < d[v] + e.coast){
  28. d[e.to] = d[v] + e.coast;
  29. q.push(P(d[e.to], e.to));
  30. }
  31. }
  32. }
  33. return;
  34. }
  35. int main()
  36. {
  37. scanf("%d", &n);
  38. for(int i = 1; i <= n; i ++)
  39. scanf("%d", &a[i]);
  40. //加边建图.
  41. for(int i = 2; i < n; i ++){
  42. add_edge(i - 2, i + 1, 3 * a[i]);
  43. add_edge(i + 1, i - 2, -3 * a[i] - 2);
  44. }
  45. add_edge(0, 2, 2 * a[1]);
  46. add_edge(2, 0, -2 * a[1] - 1);
  47. add_edge(n - 2, n, 2 * a[n]);
  48. add_edge(n, n - 2, -2 * a[n] - 1);
  49. for(int i = 1; i <= n; i ++)
  50. add_edge(i - 1, i, 1);
  51. dijsktra(); //跑一遍dijsktra.
  52. for(int i = 1; i <= n; i ++)
  53. printf("%d ", d[i] - d[i - 1]); //d[i]是前缀和数组.
  54. return 0;
  55. }

ccf-csp201809题解的更多相关文章

  1. IOI2015 Boxes

    Description 给出一个环形,n个点,每次只能访问k个点,求最短距离. Sol 贪心. CCF的题解. 首先只会最多走一趟环形,根据抽屉原理,如果一边不足k个才会到另一边,所以对于第二次以上的 ...

  2. CCF考试真题题解

    CCF考试认证:题解参考博客http://blog.csdn.net/u014578266/article/details/45221841 问题描述 试题编号: - 试题名称: 图像旋转 时间限制: ...

  3. CCF计算机职业资格认证考试题解

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF计算机职业资格认证考试题解 CCF计算机软件能力认证(简称CCF CSP认证)是CCF计算机职业资格认证系 ...

  4. 【实(dou)力(bi)首(mai)发(meng)】第四次CCF软件能力认证题解

    这次的题总体上相对前三次偏简单.由于实力有限,就分析前四题.     试题编号:    201503-1 试题名称:    图像旋转 时间限制:    5.0s 内存限制:    256.0MB 问题 ...

  5. 第四届CCF软件能力认证(CSP2015) 第五题(最小花费)题解

    [问题描述] C国共有$n$个城市.有$n-1$条双向道路,每条道路连接两个城市,任意两个城市之间能互相到达.小R来到C国旅行,他共规划了$m$条旅行的路线, 第$i$条旅行路线的起点是$s_i$,终 ...

  6. CCF统一省选 Day2 题解

    此题解是教练给我的作业,AK了本场比赛的人,以及认为题目简单的人可以不必看 T1 算法一 暴力枚举对信号站顺序的不同排列,然后对代价取\(\min\)即可. 时间复杂度\(O(m! \cdot n)\ ...

  7. ccf 201503-5 最小花费 这题交上去只有10分嗨!求大佬的题解啊

    问题描述 C国共有n个城市.有n-1条双向道路,每条道路连接两个城市,任意两个城市之间能互相到达.小R来到C国旅行,他共规划了m条旅行的路线,第i条旅行路线的起点是si,终点是ti.在旅行过程中,小R ...

  8. 题解 P5065 【[Ynoi2014]不归之人与望眼欲穿的人们】

    出现了一篇跑得炒鸡慢的题解! noteskey 无 fuck 说,好像就是整个数列分块然后合并区间...什么的吧 对于每块内部就是算一下前缀信息.后缀信息(就是以 第一个点/最后一个点 为一个边界,不 ...

  9. 题解 SP26045 【GCDMAT2 - GCD OF MATRIX (hard)】

    承接一下洛咕上的题解,这里基本就是谈谈优化,放个代码的 我们发现这里的常数主要来自于除法,那么我们优化除法次数,把所有的 \(n/1...n/s\) (\(s=\sqrt n\))存下来,然后归并排( ...

  10. CCF CSP 201703-3 Markdown

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-3 Markdown 问题描述 Markdown 是一种很流行的轻量级标记语言(l ...

随机推荐

  1. 基于iCamera测试mt9m034 1280X960 高动态相机模块小结

    基于iCamera测试mt9m034 高动态相机模块小结 首先看看此模块的特性 mt9m034 高动态 CMOS模块 1280*960像素 5.48 V/lux-sec >115db 摄像头模块 ...

  2. .NET Core RSA 指南与增强扩展 RSAExtensions

    一. 前言 RSA 作为最常用的非对称加密算法,在我们的实际使用中还是比较常见的,特别是对接支付十有八九都会遇到,或者是其他需要数据安全的业务场景.在 .NET Framework 以及 .NET C ...

  3. 大数据学习笔记——Hadoop编程实战之Mapreduce

    Hadoop编程实战——Mapreduce基本功能实现 此篇博客承接上一篇总结的HDFS编程实战,将会详细地对mapreduce的各种数据分析功能进行一个整理,由于实际工作中并不会过多地涉及原理,因此 ...

  4. LInux内核配置过程

    内核版本 linux 2.6.32.2 配置内核的过程 配置内核可以通过执行 make menuconfig 来进行,下面分析该命令的执行流程 执行该目标 %config: scripts_basic ...

  5. python爬虫--模拟12306登录

    模拟12306登录 超级鹰: #!/usr/bin/env python # coding:utf-8 import requests from hashlib import md5 class Ch ...

  6. SSM非springboot配置swagger2

    前提:maven,ssm,不是springboot项目 1.在maven中添加依赖 <!-- Swagger2 Begin --> <!--springfox的核心jar包--> ...

  7. .Net,Java,Redis,Vue等技术视屏教程分享(不定期更新)

    前言 作为一个资深的收藏家决定把我收集的那些精品资源不定时更新分享给大家 .所有资源全是收集余网络或为大佬分享,内容仅供观摩学习交流之用.如果犯了您的权益,请联系我. 2019.12.19更新 ASP ...

  8. 如何利用PS将照片背景替换为白色

    需求:将照片中的蓝底换成白底: 操作步骤: 1.打开图片,点击背景图层: 2.利用套索,选中除背景外的区域: 3.右键,反选: 4.填充为“白色”,确定,保存:

  9. linux globbing文件名通配

    globbing:文件名通配 元字符: *:匹配任意长度的任意字符 ?:匹配任意单个字符 []:匹配指定范围内的任意单个字符 [a-z]或者[A-Z]或者[[:alpha:]]:匹配任意一个字母 [[ ...

  10. 如何在 Chrome中导出、导入书签和密码

    目录 书签 密码 书签 1.导出 点击浏览器右上角的三小点,选择"书签",再选择"书签管理器",进入如下页面 点击蓝色书签栏右上角的三小点,选择"导出 ...