蓝桥杯抱佛脚第四天|前缀和,差分对应练习

题单:【蓝桥杯】蓝桥杯省一秘诀(国赛题单看简介) - 题单 - 洛谷 | 计算机科学教育新生态

状态:差分没看太懂,前缀和倒是有熟练了一点

P8649 [蓝桥杯 2017 省 B] k 倍区间

题目链接:[P8649 蓝桥杯 2017 省 B] k 倍区间 - 洛谷

题目描述

给定一个长度为 N 的数列,A 1,A 2,⋯A**N ,如果其中一段连续的子序列 A**i ,A**i +1,⋯A**j (ij ) 之和是 K 的倍数,我们就称这个区间 [i ,j ] 是 K 倍区间。

你能求出数列中总共有多少个 K 倍区间吗?

输入格式

第一行包含两个整数 NK (1≤N ,K≤105)。

以下 N 行每行包含一个整数 A**i (1≤A**i≤105)。

输出格式

输出一个整数,代表 K 倍区间的数目。

输入输出样例

输入 #1

复制代码
5 2
1  
2  
3  
4  
5  

输出 #1

复制代码
6

说明/提示

时限 2 秒, 256M。蓝桥杯 2017 年第八届

这道题要是模拟的话会超时,依旧使用前缀和的思想来解决。子区间 [i, j] 的和等于 pre[j] - pre[i-1](其中 pre[0]=0,pre[t] 表示前 t 个元素的和)。该和是 K 的倍数当且仅当 (pre[j] - pre[i-1]) % K == 0,即 pre[j] % K == pre[i-1] % K。所以前缀和里存的是前缀和取模后的余数,

复制代码
#include <bits/stdc++.h>
using namespace std;
int main() {
    int N, K;
    cin >> N >> K;    
    vector<long long> cnt(K, 0);  // 统计每个余数出现的次数
    cnt[0] = 1;                   // 初始前缀和为0,余数为0  
    long long ans = 0;            //存放最后的结果
    long long sum = 0;            // 当前前缀和   
    for (int i = 0; i < N; ++i) {
        int x;
        cin >> x;
        sum = (sum + x) % K;      // 更新当前前缀和模K
        ans += cnt[sum];          // 加上之前相同余数的个数
        cnt[sum]++;               // 当前余数出现次数加1
    }    
    cout << ans << endl;
    return 0;
}

CF816B Karen and Coffee

题目链接:CF816B Karen and Coffee - 洛谷

题目描述

为了在上课时保持清醒和专注,Karen 需要喝点咖啡!

Karen 是一位咖啡爱好者,她想知道冲泡完美咖啡的最佳温度。实际上,她花了一些时间阅读了几本食谱,包括备受赞誉的《The Art of the Covfefe》。

她一共掌握了 n 种咖啡配方。第 i 个配方建议咖啡应在 l**ir**i 度(包含端点)之间冲泡,以获得最佳口感。

Karen 认为,如果有至少 k 个配方推荐某个温度,则该温度为可接受温度。

Karen 的想法总是变化多端,于是她总共提出了 q 个问题。每个问题,她都会给定一个温度范围 ab,想让你告诉她,在这个范围内有多少个可接受的整数温度。

输入格式

输入的第一行包含三个整数 n , k (1≤kn ≤200000)、q (1≤q≤200000),分别表示配方数量、某个温度被判定为可接受所需的最少配方数,以及 Karen 提出的查询个数。

接下来的 n 行描述每个配方。具体地,第 i 行包含两个整数 l**ir**i (1≤l**ir**i ≤200000),表示第 i 个配方推荐咖啡应在 l**ir**i 度(包含端点)之间冲泡。

接下来的 q 行描述各个问题。每行包含两个整数 ab (1≤ab ≤200000),表示她想知道在 ab(包含端点)度之间有多少个可接受的整数温度。

输出格式

对于每一个问题,输出一行一个整数,表示在 ab 度之间有多少个可接受的整数温度。

输入输出样例

输入 #1

复制代码
3 2 4
91 94
92 97
97 99
92 94
93 97
95 96
90 100

输出 #1

复制代码
3
3
0
4

输入 #2

复制代码
2 1 1
1 1
200000 200000
90 100

输出 #2

复制代码
0

说明/提示

在第一个测试点中,Karen 掌握了 3 个配方。

  1. 第一个推荐温度区间为 91 到 94 度(包含端点)。

  2. 第二个推荐温度区间为 92 到 97 度(包含端点)。

  3. 第三个推荐温度区间为 97 到 99 度(包含端点)。

只要某个温度区间内至少有 2 个配方推荐,则该温度为可接受温度。

她一共提出了 4 个问题。

在第一个询问中,她想知道在 92 到 94 度之间的可接受整数温度有多少。答案是 3,因为 92, 93, 94 度都是可接受的。

在第二个询问中,她想知道在 93 到 97 度之间的可接受整数温度有多少。答案是 3,因为 93, 94, 97 度都是可接受的。

在第三个询问中,她想知道在 95 到 96 度之间的可接受整数温度有多少。没有可接受的温度。

在最后一个询问中,她想知道在 90 到 100 度之间有多少个可接受的整数温度。答案是 4,分别是 92, 93,94,97 度。

在第二个测试点中,Karen 掌握了 2 个配方。

  1. 第一个配方建议只在 1 度冲泡咖啡。

  2. 第二个配方建议只在 200000 度冲泡咖啡。

只要某个温度区间内至少有 1 个配方推荐,则该温度为可接受温度。

她有且仅有一个问题,询问在合理范围内有多少可接受整数温度。实际上没有。

这是一个典型的差分数组 +和前缀和的应用,用于解决区间覆盖计数和区间查询的问题。假设我们有一个数组 cover,长度等于温度范围,初始全为 0。差分数组统计每个温度的覆盖次数。差分数组 diff 是这样定义的:diff[i] 表示 cover[i] 与 cover[i-1] 的差值(即 cover[i] - cover[i-1])。反过来,如果我们知道 diff,就可以通过前缀和还原出 cover:

现在,如果我们想在区间 [l, r] 上每个位置都加 1,这在差分数组上如何体现?

  • l 位置加 1,会让从 l 开始的 cover 都增加 1。

  • 为了不让 r+1 及以后的位置也增加,我们还要在 r+1 位置减 1。

    diff[l] += 1 diff[r+1] -= 1

    这样,最后对 diff 求一遍前缀和,就能得到每个温度的实际覆盖次数 cover。

复制代码
#include<stdio.h>
using namespace std;
int f[200005];
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    int i;
    int max=0;
    for(i=1;i<=n;i++){//差分代码
        int a,b;
        scanf("%d%d",&a,&b);
        f[a]+=1;f[b+1]-=1;
        if(b>max)max=b;
    }
    for(i=1;i<=max;i++){
        f[i]=f[i-1]+f[i];
    }
    for(i=1;i<=200000;i++){//前缀和
        if(f[i]>=m)f[i]=1+f[i-1];
        else f[i]=f[i-1];
    }
    for(i=1;i<=k;i++){
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",f[r]-f[l-1]);//前缀和计算
    }
    return 0;
} 
​
相关推荐
freexyn2 小时前
Matlab入门自学七十四:坐标系转换,直角坐标、极坐标和球坐标的转换
开发语言·算法·matlab
咱就是说不配啊2 小时前
3.20打卡day34
数据结构·c++·算法
小张会进步2 小时前
数组:二维数组
java·javascript·算法
佑白雪乐2 小时前
LCR 175. 计算二叉树的深度
算法·深度优先
阿Y加油吧2 小时前
力扣打卡day07——最大子数组和、合并区间
算法
_饭团3 小时前
字符串函数全解析:12 种核心函数的使用与底层模拟实现
c语言·开发语言·学习·考研·面试·蓝桥杯
想吃火锅10053 小时前
【leetcode】105. 从前序与中序遍历序列构造二叉树
算法·leetcode·职场和发展
2401_831824963 小时前
嵌入式C++驱动开发
开发语言·c++·算法
靠沿3 小时前
【优选算法】专题十八——BFS解决拓扑排序问题
算法·宽度优先