算法--前缀和技巧 (蓝桥杯123-灵能传输)

news/2024/4/24 12:12:57/文章来源:https://blog.csdn.net/qq_56717234/article/details/130329058

文章目录

  • 什么是前缀和
  • 用途
  • 什么时候用
  • 例题
    • [蓝桥杯 2021 国 ABC] 123
      • 题目描述
        • 输入格式
        • 输出格式
        • 样例 #1
        • 样例输入 #1
          • 样例输出 #1
        • 提示
      • 思路
      • 代码
    • 灵能传输(蓝桥杯96%,洛谷ac)
    • [蓝桥杯 2019 省 B] 灵能传输
      • 题目背景
        • 题目描述
        • 输入格式
        • 输出格式
        • 样例 #1
          • 样例输入 #1
          • 样例输出 #1
        • 样例 #2
          • 样例输入 #2
          • 样例输出 #2
        • 样例 #3
          • 样例输入 #3
          • 样例输出 #3
        • 提示
    • 思路
    • 代码

什么是前缀和

如果一个数组a的元素为 a 1 , a 2 , a 3 , a 4 , a 5 . . . a i a_1,a_2,a_3,a_4,a_5...a_i a1,a2,a3,a4,a5...ai.
而另一个数组b为 a 1 , a 1 + a 2 , a 1 + a 2 + a 3 . . . . , a 1 + . . + a i a_1,a_1+a_2,a_1+a_2+a_3....,a_1+..+a_i a1,a1+a2,a1+a2+a3....,a1+..+ai
那么数组b就是a的前缀和了。

用途

那么前缀和有些什么用呢。
我们让 b 1 , b 2 . . . b i b_1,b_2...b_i b1,b2...bi代表b的元素
那么我们可以轻易的用一次减法得到某个区间的和如 a 5 + a 6 + . . . + a 100 a_5+a_6+...+a_{100} a5+a6+...+a100等于 b 100 − b 5 b_{100}-b_5 b100b5得到这个差值,而不用每次都一个个加。

什么时候用

  1. 经常需要求区间和
  2. 而在一些题目中,数组a在题意中是变化的,而其前缀和不变,那么很有可能就是使用前缀和

例题

[蓝桥杯 2021 国 ABC] 123

题目描述

小蓝发现了一个有趣的数列, 这个数列的前几项如下:

1 , 1 , 2 , 1 , 2 , 3 , 1 , 2 , 3 , 4 , … 1,1,2,1,2,3,1,2,3,4, \ldots 1,1,2,1,2,3,1,2,3,4,

小蓝发现, 这个数列前 1 1 1 项是整数 1 1 1 , 接下来 2 2 2 项是整数 1 1 1 2 2 2 , 接下来 3 3 3 项是整数 1 1 1 3 3 3 , 接下来 4 4 4 项是整数 1 1 1 4 4 4 , 依次类推。

小蓝想知道, 这个数列中, 连续一段的和是多少。

输入格式

输入的第一行包含一个整数 T T T, 表示询问的个数。

接下来 T T T 行, 每行包含一组询问, 其中第 i i i 行包含两个整数 l i l_{i} li r i r_{i} ri, 表示 询问数列中第 l i l_{i} li 个数到第 r i r_{i} ri 个数的和。

输出格式

输出 T T T 行, 每行包含一个整数表示对应询问的答案。

样例 #1

样例输入 #1

3
1 1
1 3
5 8
样例输出 #1
1
4
8

提示

对于 10 % 10 \% 10% 的评测用例, 1 ≤ T ≤ 30 , 1 ≤ l i ≤ r i ≤ 100 1 \leq T \leq 30,1 \leq l_{i} \leq r_{i} \leq 100 1T30,1liri100
对于 20 % 20 \% 20% 的评测用例, 1 ≤ T ≤ 100 , 1 ≤ l i ≤ r i ≤ 1000 1 \leq T \leq 100,1 \leq l_{i} \leq r_{i} \leq 1000 1T100,1liri1000
对于 40 % 40 \% 40% 的评测用例, 1 ≤ T ≤ 1000 , 1 ≤ l i ≤ r i ≤ 1 0 6 1 \leq T \leq 1000,1 \leq l_{i} \leq r_{i} \leq 10^{6} 1T1000,1liri106
对于 70 % 70 \% 70% 的评测用例, 1 ≤ T ≤ 10000 , 1 ≤ l i ≤ r i ≤ 1 0 9 1 \leq T \leq 10000,1 \leq l_{i} \leq r_{i} \leq 10^{9} 1T10000,1liri109
对于 80 % 80 \% 80% 的评测用例, 1 ≤ T ≤ 1000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 1000,1 \leq l_{i} \leq r_{i} \leq 10^{12} 1T1000,1liri1012
对于 90 % 90 \% 90% 的评测用例, 1 ≤ T ≤ 10000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 10000,1 \leq l_{i} \leq r_{i} \leq 10^{12} 1T10000,1liri1012
对于所有评测用例, 1 ≤ T ≤ 100000 , 1 ≤ l i ≤ r i ≤ 1 0 12 1 \leq T \leq 100000,1 \leq l_{i} \leq r_{i} \leq 10^{12} 1T100000,1liri1012
蓝桥杯 2021 国赛 A 组 E 题(B 组 F 题,C 组 F 题)。

思路

根据题目可以知道是得到某个范围的和。那么我们就可以考虑到前缀和。
我们看项,(num)项的和值是 1 , 1 + 2 , 1 + 2 + 3 , 1 + 2 + 3 + 4.... 1,1+2,1+2+3,1+2+3+4.... 1,1+2,1+2+3,1+2+3+4....
每一项的项数为 1 , 2 , 3 , 4... 1,2,3,4... 1234...个数。

但是我们需要的是从开头的项,那么用前缀和得到这样的表示数量的数组 1 , 3 , 6 , 10.... 1,3,6,10.... 1,3,6,10....。而我们发现这个数组其实和num数组一样的。我们需要求某个范围的和,那么我们构造一个前缀和(sum数组) 1 , 4 , 10 , 16... 1,4,10,16... 141016...如果想要求6到10项和就算sum[4]-sum[3]就可以了。如果想要5到8呢。
我们也可以先得到sum[4]-sum[3]然后减去9,10代表的加上5,6就是答案了。

那么我们只剩下一个问题了,如何得到4和3还有减去的数和加上的数。
我们发现这个围绕的都是6和10项。10是num[4]代表的,6是num[3]代表的。
加和减是和6,10的差距。

如何得到呢。我们可以发现num是顺序的,就可以用二分,得到其小于等于这个值的位置。(java直接Arrays.binarySearch插入点就可以了)

emm好像还差了,9、10、5、6代表的数如何求。我们可以知道,对于10的数一定是4,因为每一项都是从1到i来的,所以最后一个一定是i。第一个是1.
那么我们可以用一个求和公式来计算, ( 首项 + 末项 ) ∗ 项数 / 2 (首项+末项)*项数/2 (首项+末项)项数/2
项数num[i] - 当前项。末项为i,首项为i-项数。

下面来根据代码食用。

代码

import java.io.*;
import java.util.Arrays;public class Main {static final PrintWriter print = new PrintWriter(System.out);// 更快的输入输出static final StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));public static int nextInt() throws IOException {st.nextToken();return (int) st.nval;}public static long nextLong() throws IOException {st.nextToken();return (long) st.nval;}public static void main(String[] args) throws IOException {int m = 2000000;long[] num = new long[m];//构造前缀和numfor (int i = 1; i < m; i++) {num[i] = num[i - 1] + i;}//构造前缀和sumlong[] sum = Arrays.copyOf(num, m);Arrays.parallelPrefix(sum, Long::sum);//注释掉的是因为最大数据在10的12次方,测试m是否能够到达最大
//        System.out.println(num[m-1]);
//        System.out.println(sum[m-1]);int n = nextInt();for (int i = 0; i < n; i++) {long a = nextLong();long b = nextLong();//寻找下标。int x = Arrays.binarySearch(num, a);int y = Arrays.binarySearch(num, b);x = x > 0 ? x : -x - 1;y = y > 0 ? y : -y - 1;//获取区间和long ans = sum[y] - sum[x];//获取项数long z = num[y] - b;//求和ans -= (2 * y - z + 1) * z / 2;z = num[x] - a + 1;ans += (2 * x - z + 1) * z / 2;//获得答案print.println(ans);}print.flush();}
}

灵能传输(蓝桥杯96%,洛谷ac)

我只做到96%,不能ac,最后一个超时了。但是在洛谷没有超时
在这里插入图片描述
在这里插入图片描述

[蓝桥杯 2019 省 B] 灵能传输

题目背景

在游戏《星际争霸 II》中,高阶圣堂武士作为星灵的重要 AOE 单位,在游戏的中后期发挥着重要的作用,其技能“灵能风暴”可以消耗大量的灵能对一片区域内的敌军造成毁灭性的伤害。经常用于对抗人类的生化部队和虫族的刺蛇飞龙等低血量单位

题目描述

你控制着 n n n 名高阶圣堂武士,方便起见标为 1 , 2 , ⋯ , n 1,2, \cdots,n 1,2,,n。每名高阶圣堂武士需要一定的灵能来战斗,每个人有一个灵能值 a i a_i ai 表示其拥有的灵能的多少( a i a_i ai 非负表示这名高阶圣堂武士比在最佳状态下多余了 a i a_i ai 点灵能, a i a_i ai 为负则表示这名高阶圣堂武士还需要 − a i -a_i ai 点灵能才能到达最佳战斗状态)。现在系统赋予了你的高阶圣堂武士一个能力,传递灵能,每次你可以选择一个 i ∈ [ 2 , n − 1 ] i \in[2,n-1] i[2,n1],若 a i ≥ 0 a_i \ge 0 ai0 则其两旁的高阶圣堂武士,也就是 i − 1 i-1 i1 i + 1 i+1 i+1 这两名高阶圣堂武士会从 i i i 这名高阶圣堂武士这里各抽取 a i a_i ai 点灵能;若 a i < 0 a_i<0 ai<0 则其两旁的高阶圣堂武士,也就是 i − 1 , i + 1 i-1,i+1 i1,i+1 这两名高阶圣堂武士会给 i i i 这名高阶圣堂武士 − a i -a_i ai 点灵能。形式化来讲就是 ( a i − 1 , a i , a i + 1 ) ← ( a i − 1 + a i , − a i , a i + 1 + a i ) (a_{i-1},a_i,a_{i+1})\leftarrow (a_{i-1}+a_i,-a_i,a_{i+1}+a_i) (ai1,ai,ai+1)(ai1+ai,ai,ai+1+ai)

灵能是非常高效的作战工具,同时也非常危险且不稳定,一位高阶圣堂武士拥有的灵能过多或者过少都不好,定义一组高阶圣堂武士的不稳定度为 max ⁡ i = 1 n { ∣ a i ∣ } \max\limits_{i=1}^n\{|a_i|\} i=1maxn{ai},请你通过不限次数的传递灵能操作使得你控制的这一组高阶圣堂武士的不稳定度最小。

输入格式

本题包含多组询问。输入的第一行包含一个正整数 T T T 表示询问组数。

接下来依次输入每一组询问。

每组询问的第一行包含一个正整数 n n n,表示高阶圣堂武士的数量。

接下来一行包含 n n n 个数 a 1 , a 2 , ⋯ , a n a_1,a_2, \cdots,a_n a1,a2,,an

输出格式

输出 T T T 行。每行一个整数依次表示每组询问的答案。

样例 #1

样例输入 #1
3 3
5 -2 3
4
0 0 0 0
3
1 2 3
样例输出 #1
3 0 3

样例 #2

样例输入 #2
3 4
-1 -2 -3 7
4
2 3 4 -8
5
-1 -1 6 -1 -1
样例输出 #2
5 7 4

样例 #3

样例输入 #3
见文件trans3.in。
样例输出 #3
见文件trans3.ans。

提示

【样例说明】

对于第一组询问:

2 2 2 号高阶圣堂武士进行传输操作后 a 1 = 3 a_1=3 a1=3 a 2 = 2 a_2=2 a2=2 a 3 = 1 a_3=1 a3=1。答案为 3 3 3

对于第二组询问:

这一组高阶圣堂武士拥有的灵能都正好可以让他们达到最佳战斗状态。

【数据规模与约定】

对于所有评测用例, T ≤ 3 T \le 3 T3 3 ≤ n ≤ 3 × 1 0 5 3 \le n \le 3\times10^5 3n3×105 ∣ a i ∣ ≤ 1 0 9 |a_i| \le 10^9 ai109

蓝桥杯 2019 年省赛 B 组 J 题。

思路

我们看到这句话 ( a i − 1 , a i , a i + 1 ) ← ( a i − 1 + a i , − a i , a i + 1 + a i ) (a_{i-1},a_i,a_{i+1})\leftarrow (a_{i-1}+a_i,-a_i,a_{i+1}+a_i) (ai1,ai,ai+1)(ai1+ai,ai,ai+1+ai)
其前缀和 ( a i − 1 , a i − 1 + a i , a i − 1 + a i + a i + 1 ) ← ( a i − 1 + a i , a i − 1 + a i + a i + 1 ) (a_{i-1},a_{i-1}+a_i,a_{i-1}+a_{i}+a_{i+1})\leftarrow(a_{i-1}+a_i,a_{i-1}+a_{i}+a_{i+1}) (ai1,ai1+ai,ai1+ai+ai+1)(ai1+ai,ai1+ai+ai+1)
后面前缀和就用s表示了就是 s i − 1 , s i , s i + 1 ← s i , s i − 1 , s i + 1 s_{i-1},s_{i},s{i+1}\leftarrow s_{i},s{i-1},s{i+1} si1,si,si+1si,si1,si+1
我们可以发现,每次操作前缀和都只是换了个变罢了。

而我们题目的意思就是让2项的差值的最大值要最小。也就是 m a x ∣ s n − s n − 1 ∣ max|s_n - s_{n-1}| maxsnsn1最小
那么如何可以到最小呢。

猜测是顺序最小,我们来具体看看。看图,这个应该还是很明显的

在这里插入图片描述
我们对其顺序排序就可以了。但是也没有就此就结束了。最后一个是不能进行交换的,

还有个问题就是有负数。所以我们需要一个s0=0来衡量一下。
排序之后。
在这里插入图片描述
s0到min->sn->max->sn我们怎么来选择呢,这部分是有重复的。
我们是怎么来选呢,是隔一个选还是2个
我们来看1个的
在这里插入图片描述
2个的
在这里插入图片描述
2个的这个最大跨度肯定会比1个的要大呀,所以我们隔着一个选一个。

代码

import java.io.*;
import java.util.Arrays;public class Main {static final PrintWriter print = new PrintWriter(System.out);static final StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));public static int nextInt() throws IOException {st.nextToken();return (int) st.nval;}public static long nextLong() throws IOException {st.nextToken();return (long) st.nval;}public static void main(String[] args) throws IOException {int t = nextInt();for (int k = 0; k < t; k++) {int n = nextInt();long[] a = new long[n + 1];// 构造前缀和for (int i = 1; i <= n; i++) {a[i] = nextInt() + a[i - 1];}
//            for (int i = 1; i <= n; i++) {
//                a[i] = nextInt();
//            }
//            Arrays.parallelPrefix(a, Long::sum);long n0 = Math.min(a[0], a[n]);long nn = Math.max(a[0], a[n]);//排序Arrays.sort(a);//找到s0和snint s0 = 0,sn = 0;for (int i = 0; i < n + 1; i++) {if (a[i] == n0) {s0 = i;break;}}for (int i = n; i >= 0; i--) {if (a[i] == nn) {sn = i;break;}}//找最大值,我们选用标记的方法来解决重复的问题long ans = 0;long[] b = new long[n + 1];boolean[] f = new boolean[n + 1];int l = 0, r = n;for (int i = s0; i >= 0; i -= 2) {b[l++] = a[i];f[i] = true;}for (int i = sn; i <= n; i += 2) {b[r--] = a[i];f[i] = true;}for (int i = 0; i <= n; i++) {if (!f[i])b[l++] = a[i];}for (int i = 1; i <= n; i++) {ans = Math.max(ans,Math.abs(b[i]-b[i-1]));}print.println(ans);}print.flush();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_102397.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode -21.合并两个有序链表 -83.删除排序链表中的重复元素】

Leetcode Leetcode-21.合并两个有序链表Leetcode-83.删除排序链表中的重复元素 Leetcode-21.合并两个有序链表 题目&#xff1a;将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 […

【Web3.0大势所趋】我看到了互联网未来的模样

前言 Web3.0 是一个越来越受到关注的话题&#xff0c;它被认为将会带来天翻地覆的变化。本文我们一起来谈谈 Web3.0 的概念、特点和优势&#xff0c;并探讨它为什么如此重要和具有革命性的。 文章目录 前言Web3.0是什么Web3.0的技术Web3.0的优势总结 Web3.0是什么 Web3.0: 是下…

MATLAB实现图像滤波及噪声消除

图像增强是指根据特定的需要突出一幅图像中的某些信息&#xff0c;同时削弱或去除某些不需要的信息的处理方法。其主要目的是使处理后的图像对某种特定的应用来说&#xff0c;比原始图像更适用。因此&#xff0c;这类处理是为了某种应用目的而去改善图像质量的。处理的结果使图…

最短路径Floyd与区间DP

floyd算法是求最短路径的算法&#xff0c;算法复杂度为n(o^3),其优点在于能够一次求解所有点到其他点的最短路径&#xff0c;不需要其他运算&#xff0c;使用二维数组存储。其三层循环自外向内分别为&#xff1a;中间点&#xff0c;起始点和终点。状态方程为&#xff1a; num[…

JVM原理

JVM 什么是JVM&#xff1f; JVM是一种虚拟出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 JVM有自己完善的硬件架构&#xff0c;如处理器、堆栈、寄存器等&#xff0c;还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。 使用J…

智慧管廊监控与报警管控一体化系统解决方案

摘要&#xff1a;智慧管廊监控与报警管控是一项综合性质较高的管控操作系统。在各项系统结构之间因为技术管理体系之间的差异&#xff0c;所评价的标准也有着不同的区分&#xff0c;导致各项标准之间难以实现相互之间的联通。这种形式下就需要实现环境与设备之间的监控管理、通…

(IPC)进程间通信的常用的两种方式——管道、共享内存

前言&#xff1a; 众所周知&#xff0c;不同的进程之间&#xff0c;在正常情况下&#xff0c;由于其拥有独立的PCB、上下文等原因&#xff0c;每个进程都是独立且互不干扰&#xff0c;这不仅保证了进程的安全&#xff0c;也降低了OS对于进程的管理成本。 但是通常情况下&…

01-yolo算法

要点&#xff1a; 归纳 YOLOv5 github 1 YOLO v1 1) 将一幅图像分成SxS个网格(grid cell)&#xff0c;如果某个object的中心 落在这个网格中&#xff0c;则这个网格就负责预测这个object。 2)每个网格要预测B个bounding box&#xff0c;每个bounding box 除了要预测位置之…

倾斜摄影三维模型、激光点云、正射影像、数字高程模型如何实现在线浏览?

四维轻云是成都远石技术团队基于浏览器打造的一款地理空间数据管理云平台&#xff0c;可实现TB级大规模倾斜摄影三维模型发布管理&#xff0c;并支持私有化部署和高阶功能定制化开发。 1、注册登录 首先在四维轻云官网点击「立即试用」按钮&#xff0c;进入登录页面并点击「注…

C# 特性(Attribute)

一、特性&#xff08;Attribute&#xff09;定义 特性&#xff08;Attribute&#xff09;是用于在运行时传递程序中各种元素&#xff08;比如类、方法、结构、枚举、组件等&#xff09;的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。 特性使用中括号…

2023年制造业产品经理考NPDP有什么用?

产品经理国际资格认证NPDP是新产品开发方面的认证&#xff0c;集理论、方法与实践为一体的全方位的知识体系&#xff0c;为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。 【认证机构】 产品开发与管理协会&#xff08;PDMA&#xff09;成立于1979年&#xff0c;是…

键盘录入及标识符

键盘录入 键盘录入介绍&#xff1a; ●为什么要有键盘录入? 目的&#xff1a;为了让我们操作的数据,变得更加灵活 举例&#xff1a;int a10; 这里a虽然是个变量&#xff0c;但记录的值&#xff0c;却是手动写死的。 提问&#xff1a;能不能让a变量记录的值&#xff0c;灵活…

electron编译环境搭建和第一个桌面应用例子

前言 Electron是基于Chromium和Node.js实现的&#xff0c;所以开发人员所需要使用到的前端技术主要包括以下方面&#xff1a; 1、Html、CSS、JavaScript、ES6 2、前端开发工具Vue、Angular、React等的一种 3、其他网络、缓存、通讯、系统、跟踪等前端技术 4、对Vscode编辑…

JUC高级十二-ReentrantLock、ReentrantReadWriteLock、StampedLock

无锁→独占锁→读写锁→邮戳锁 1. 关于锁的大厂面试题 你知道Java里面有哪些锁?你说你用过读写锁&#xff0c;锁饥饿问题是什么&#xff1f;有没有比读写锁更快的锁&#xff1f;StampedLock知道吗?(邮戳锁/票据锁)ReentrantReadWriteLock有锁降级机制策略你知道吗&#xff1…

总结827

学习目标&#xff1a; 4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 学习内容&#xff1a; 高等数学&#xff1a;刷1800&#xff0c;做了26道计算题&#xff0c;记录两道错题&#xff0c;搞懂了&#xff0c;但并不…

家庭智能开关通断—Homekit智能

智能通断器&#xff0c;也叫开关模块&#xff0c;可以非常方便地接入家中原有开关、插座、灯具、电器的线路中&#xff0c;通过手机App或者语音即可控制电路通断&#xff0c;轻松实现原有家居设备的智能化改造。 随着智能家居概念的普及&#xff0c;越来越多的人想将自己的家改…

HuggingFace入门教程--环境搭建

HuggingFace中文直译为”拥抱脸“&#xff0c;是最近非常火爆的一个人工智能社区&#xff0c;官网地址是&#xff1a;https://huggingface.co/ .关于HuggingFace的相关介绍大家可以自行百度。本文主要为刚入人工智能坑的小白指下路&#xff0c;同时也是逼着自己记录下学习过程中…

【ctfshow】命令执行->web29-web44

前言 半夜网抑云听歌听emo了 z 刷会儿题不然睡不着了呜呜呜 红中(hong_zh0) CSDN内容合伙人、2023年新星计划web安全方向导师、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 吉林师范大学网安大一的一名普通学生、搞网安论文拿了回大挑校二、 阿里云专家博…

线性链表 反转 -(递归与非递归算法)_20230420

线性链表 反转 -(递归与非递归算法)_20230420 前言 线性链表反转是非常有趣的算法&#xff0c;它可以采用多种方式实现&#xff0c;比较简洁的方法是递归反转&#xff1b;传统的方式是利用迭代反转&#xff0c;设定三个变量&#xff0c;采用类似滚动数组的方式&#xff0c;实…

qt中使用 ui 文件进行界面设计

目录 1、创建 Qt 应用 ​2、项目创建成功 3、直接点击打开 mainwindow.ui 文件 4、随便从左边侧边栏拖拽一个空间到 界面设计区域 5、在右侧边栏右键点击 pushButton 控件&#xff0c;点击转到槽 6、根据实际需要选择对应的信号&#xff0c;我这里方便演示选择 clicked&a…