CCF-CSP 202203 赛题训练

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF-CSP 202203 赛题训练相关的知识,希望对你有一定的参考价值。

CCF-CSP 202203 赛题训练

未初始化警告

题意:判断等式右边是否在左边出现过,出现过说明赋值过,考虑使用set<>或者数组都可以。

10 7

1 2

3 3

3 0

3 3

6 2

2 1

8 2

3

样例解释 其中第一、二、五条赋值语句右值未被初始化。

#include <iostream>
using namespace std;
const int N = 1e5+10;
bool q[N];
int n, k;
int x, y;
int res;

int main() 
    q[0] = 1;  // 0为常量
    cin >> n >> k;
    while (k--) 
        cin >> x >> y;
        if (!q[y])  // 如果右边之前没存在过,便res++
            res++;
        q[x] = true;  // 将左边标记赋值
    
    cout << res << endl;
    return 0;

https://blog.csdn.net/weixin_53919192/article/details/124872609?spm=1001.2014.3001.5502

出行计划

暴力解法:给出每次核酸时间,遍历查询能否通行?

出行开始时间t满足:[q+k, q+k+c-1]:即核酸报告结果出来时间,及地点核酸要求期限。

#include<bits/stdc++.h>
using namespace std;

struct plan 
    int t, c;
p[100000+1];

int main() 
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 1; i <=n; i++) 
        cin >> p[i].t >> p[i].c;
    
    while (m--) 
        int q;
        cin >> q;
        int cnt = 0;
        for (int i = 1; i <= k; i++) 
            if (q+k <= p[i].t && p[i].t <= (q+k+p[i].c-1))
                cnt++;
        
        cout << cnt << endl;
    

差分

数组a:a[1], a[2], a[3], a[n]
数组b : b[1] ,b[2] , b[3], b[i]
使得 a数组是b数组的前缀和,b数组是a数组的差分
a[i] = b[1] + b[2] + …+ b[i]

我们要将一个数列a的[l, r]范围内加上(或减去)一个数c,可对a的差分数组b进行如下操作:

b[l] += c, b[r + 1] -= c;

本题利用差分,首先对于每一个计划,计算应在哪个时间段内做核酸使得该计划能成功通行,让该时间段上的通行数都加一。

设 q 时刻做核算;t,k , c 分别代表 t 时刻进入某场所,k 小时出核酸结果,场所需要持 c 小时以内的核酸证明。

  • 因此能够通行需要满足的条件 : q + k < = t < = q + k + c − 1 q + k <= t <= q + k + c - 1 q+k<=t<=q+k+c1 ;
  • 通过不等式变形为 : t − k − c + 1 < = q < = t − k t - k - c + 1 <= q <= t - k tkc+1<=q<=tk;

因此对于某个出行计划而言, q时刻做核酸只要满足 ② 式子即可通行。

  • 所以我们需要开辟一个数组来记录每个时间能通行的数量,
  • 当遍历完所有通行计划后,对差分数组进行还原成原始数组,
  • 就可以利用数组下标直接得到询问的结果
  1. 需要定义一个数组res用于存储 i 时刻做核酸可以通过的计划数目。因为在出行计划输入时,即可根据 ②算出满足该计划出行的做核酸的范围[a,b];
  2. 再将res数组中下标范围从 [a,b] 进行 + 1;[a,b]+1 利用差分的方法,例如[4, 9],只需要让res[4] + 1, res[10] - 1;
  3. 然后让res数组求前缀和 :res[i] = res[i-1] + res[i] ;
  4. 接着对于输入的q只需返回res[q]即可。
#include <iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 200010;
int res[N];

int main() 
    int n, m ,k;
    cin >> n >> m >> k;
    for (int i = 0; i < n; i++) 
    int t, c;
    cin >> t >> c;

    // 在[l,r]时间段内做核酸,则t时刻可进入
    int l = max(t-k-c+1, 0);
    l = min(l, 200000);
    int r = max(0, t-k);
    r = min(r, 2000000);
    // 在[l, r]时间段内能出行的次数+1
    res[l] += 1;
    res[r+1] -= 1;
    
    //利用差分计算每个时间的能出行个数
    for (int i = 1; i < 200001; i++) 
        res[i] += res[i-1];  // 累计求和
    
    for (int i = 0; i < m; i++) 
        int q;
        cin >> q;
        cout << res[q] << endl;
    
    return 0;

Link1

Link2

加油!

感谢!

努力!

以上是关于CCF-CSP 202203 赛题训练的主要内容,如果未能解决你的问题,请参考以下文章

CCF-CSP 201604 赛题训练

CCF-CSP 201612 赛题训练

CCF-CSP 201609 赛题训练

CCF-CSP 201709 赛题训练

CCF-CSP 201909 赛题训练

CCF-CSP 201812 赛题训练