首先,前缀和一般是给复杂度低于n²的算法使用的
公式为:s[i]=s[i-1]+a[i]
B3612 【深进1.例1】求区间和
题目描述
给定 n 个正整数组成的数列 a1,a2,⋯,an 和 m 个区间 [li,ri],分别求这 m 个区间的区间和。
输入格式
第一行,为一个正整数 n 。
第二行,为 n 个正整数 a1,a2,⋯,an
第三行,为一个正整数 m 。
接下来 m 行,每行为两个正整数 li,ri ,满足 1≤li≤ri≤n
输出格式
共 m 行。
第 i 行为第 i 组答案的询问。
输入输出样例
输入 #1
4 4 3 2 1 2 1 4 2 3
输出 #1
10 5
说明/提示
样例解释:第 1 到第 4 个数加起来和为 10。第 2 个数到第 3 个数加起来和为 5。
对于 50% 的数据:n,m≤1000 ;
对于 100% 的数据:1≤n,m≤10的5次方,1≤ai≤10的4次方。
解法:复杂度有10的5次方,所以使用前缀和
题解:
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
cin>>m;
while(m--)
{
int x,y;
cin>>x>>y;
cout<<s[y]-s[x-1]<<"\n";
}
注意s[y]应该减s[x-1]
P10233 [yLCPC2024] A. dx 分计算
题目背景
你说的对,但舞萌 DX 是一款由 SEGA 开发,华立科技代理,形似洗衣机的街机音乐游戏。
只要看准时机拍到所有的音符就好啦!
题目描述
在舞萌 DX 中,每个音符根据完成击打的时刻,会得到如下五种判定:
Critical Perfect:简记为P,可得 3 分 dx 分。Perfect:简记为p,可得 2 分 dx 分。Great:简记为G,可得 1 分 dx 分。Good:简记为g,不能得到 dx 分。Miss:简记为m,不能得到 dx 分。
扶苏游玩了一局舞萌 DX,她将她各个音符的判定情况按顺序使用上面的简记规则记为了一个字符串 s。规定这个字符串最左边的字符表示第一个音符的判定结果,最右边的字符表示第 ∣s∣ 个音符的判定结果,这里 ∣s∣ 表示字符串 ∣s∣ 的长度,也即整首歌的音符数。
现在,扶苏有 q 次询问,每次询问会给出两个整数 l,r,对每个询问你需要回答:这首歌的第 l 个音符到第 r 个音符(包含第 l 个和第 r 个)的判定结果共能得到多少 dx 分数?
乐曲一段区间内的音符得到的 dx 分数是这些音符分别能得到的 dx 分数之和。
输入格式
本题单个测试点内有多组测试数据,输入的第一行是一个正整数,表示数据组数 T。对每组测试数据:
第一行是一个字符串 s(1≤∣s∣≤10的7次方),表示一首歌各个音符的判定结果。保证 s 中只含字符 P,p,G,g,m。
第二行有一个整数 q(1≤q≤10的4次方),表示询问的数量。
接下来 q 行,每行两个整数 l,r(1≤l≤r≤∣s∣),表示一组询问。
数据保证单个测试点内 s 的长度之和不超过 10的7次方,q 之和不超过 10的4次方。
输出格式
对每组测试数据,按询问的顺序依次给出每个询问的答案。每个询问输出一行一个整数表示答案。
输入输出样例
输入 #1
2 PpGgm 2 1 5 4 5 PPppGGgm 5 1 2 3 4 5 6 7 7 8 8
输出 #1
6 0 6 4 2 0 0
解法:前缀和秒了,但注意这个题输入给的是字符串,还要判断
题解:
string c;
int x,y;
cin>>c>>n;
s[0]=0;
for(int i=0;i<c.size();i++)
{
if(c[i]=='P') s[i+1]=s[i]+3;
else if(c[i]=='p') s[i+1]=s[i]+2;
else if(c[i]=='G') s[i+1]=s[i]+1;
else s[i+1]=s[i];
}
for(int i=1;i<=n;i++)
{
cin>>x>>y;
cout<<s[y]-s[x-1]<<"\n";
}
P3353 在你窗外闪耀的星星
题目背景
飞逝的的时光不会模糊我对你的记忆。难以相信从我第一次见到你以来已经过去了 3 年。我仍然还生动地记得,3 年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀着你玫瑰色的脸颊。我明白,我已经沉醉于你了。之后,经过几个月的观察和窥探,你的优雅与智慧,你对待生活的态度和你对未来的愿望深切地在我心中留下了印象。你是迷人的阳光女孩,我总是梦想着与你分享余生。唉,实际上你远远超过了我最疯狂的梦想。我不知道如何桥起我与你之间的鸿沟。所以我没有任何计划,仅仅只是等待,等待一个适当的机会到来。直到现在,毕业的到来,我意识到我是个傻瓜,我应该创造机会并且抓住它而不只是等待。
这些日子里,我和我的朋友、室友、同学一个接一个地分开。我仍无法相信,在挥手之后,这些熟悉的面孔很快就会从我们的生活中消失,仅仅留下回忆。我明天就将离开学校。你已经计划远走高飞,追求你的未来,实现你的梦想。如果没有命运,也许我们不会再次相遇。所以今晚,我正在你的宿舍楼下徘徊,希望能偶然遇见你。但矛盾的是,你的美貌一定会使我心跳加速,我笨拙的舌头也许无法吐出一个字。我不记得我曾多少次经过你的宿舍楼,每次都希望看到你出现在阳台上或是窗台上。我不记得这个想法曾多少次在我的脑海中涌出:打电话叫她一起吃晚饭或是聊聊天。但每次,考虑到你的优秀和我的平凡,胆怯的优势超越勇气驱使我静静地离开。
毕业,意味着中学生活的终结。这些光荣与浪漫的时代结束。你可爱的微笑是我原来努力学习的动力,这单相思的爱情会被密封,作为一个我心灵深处的记忆。毕业,也意味着新生活的开始,一个到达光明未来的足迹。我真希望你在国外天天开心,一切顺利。同时,我将努力从幼稚中走出来,变得更加成熟。我的理想将是在现实中追求我的爱与幸福,我永远不会放弃。
再见了,我的公主!
如果有一天,在某个天涯海角,我们有机会相聚,即使是白发苍苍的男人和女人,在那个时候,我希望我们可以成为好朋友来自豪地分享这个记忆,重温年轻快乐的激情。如果这个机会永远没有到来,我希望我是天空中的星星,在你的窗外闪烁。远远地保佑着你,就像一个朋友,每天晚上陪伴在你左右,一同分享甜美的梦亦或是一同经历可怕的梦。
题目描述
现在问题来了:天空可以理解为一条数轴,在这条数轴上分布着许多颗星星,对于每颗星星都有它的位置 Xi 和自身的亮度 Bi。一个位置可能有多颗星星。而窗户所能看到的范围是一个给出的参数 W,我们看到的星星也包括窗户边缘的星星。现在,要你求出调整窗户位置后能看到星星的亮度之和最大值。
输入格式
一行 N,W,分别代表星星的数量和窗户的宽度。
余下 N 行,输入 Xi 和 Bi,代表星星的坐标和亮度。
输出格式
一个数字,代表能看到星星的最大亮度和。
输入输出样例
输入 #1
6 3 1 2 2 4 3 8 4 4 5 2 1000 1
输出 #1
16
说明/提示
样例说明:

对于 10% 的数据,W=0(没有边缘);
对于 40% 的数据,W≤1000;
对于 100% 的数据,1≤N≤10的5次方,0≤W≤10的5次方,1≤Xi≤10的5次方,1≤Bi≤100。
除 W=0 的情况外,W 均为 ≥3 的奇数。
解法:注意这里会有多颗星星重叠,所以要把它们加起来求前缀和
题解:
for(int i=1;i<=n;i++)
{
int x,b;
cin>>x>>b;
a[x]+=b;
m=max(x,m);
}
for(int i=1;i<=m;i++)
s[i]=s[i-1]+a[i];
for(int i=w;i<=100000;i++)
mx=max(mx,s[i]-s[i-w]);
错误:m在max函数里判断时写成了max(b,m)
P6568 [NOI Online #3 提高组] 水壶
题目描述
有 n 个容量无穷大的水壶,它们从 1∼n 编号,初始时 i 号水壶中装有 Ai 单位的水。
你可以进行不超过 k 次操作,每次操作需要选择一个满足 1≤x≤n−1 的编号 x,然后把 x 号水壶中的水全部倒入 x+1 号水壶中。
最后你可以任意选择恰好一个水壶,并喝掉水壶中所有的水。现在请你求出,你最多能喝到多少单位的水。
输入格式
第一行一个正整数 n,表示水壶的个数。
第二行一个非负整数 k,表示操作次数上限。
第三行 n 个非负整数,相邻两个数用空格隔开,表示水壶的初始装水量 A1, A2, ⋯, An。
输出格式
一行,仅一个非负整数,表示答案。
输入输出样例
输入 #1
10 5 890 965 256 419 296 987 45 676 976 742
输出 #1
3813
说明/提示
数据规模与约定
- 对于 10% 的数据,保证 n≤10。
- 对于 30% 的数据,保证 n≤100。
- 对于 50% 的数据,保证 n≤10的3次方。
- 对于 70% 的数据,保证 n≤10的5次方。
- 对于 100% 的数据,保证 1≤n≤10的6次方,0≤k≤n−1,0≤Ai≤10的3次方。
解法:其实就是前缀和,根刚刚那道题差不多
题解:
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
s[i]=s[i-1]+a[i];
for(int i=w;i<=n;i++)
mx=max(mx,s[i]-s[i-w-1]);
P5638 【CSGRound2】光骓者的荣耀
题目背景

小 K 又在做白日梦了。他进入到他的幻想中,发现他打下了一片江山。
题目描述
小 K 打下的江山一共有 n 个城市,城市 i 和城市 i+1 有一条双向高速公路连接,走这条路要耗费时间 ai。
小 K 为了关心人民生活,决定定期进行走访。他每一次会从 1 号城市到 n 号城市并在经过的城市进行访问。其中终点必须为城市 n。
不仅如此,他还有一个传送器,传送半径为 k,也就是可以传送到 i−k 和 i+k。如果目标城市编号小于 1 则为 1,大于 n 则为 n。
但是他的传送器电量不足,只能传送一次,况且由于一些原因,他想尽量快的完成访问,于是就想问交通部部长您最快的时间是多少。
注意:他可以不访问所有的城市,使用传送器不耗费时间。
输入格式
两行,第一行 n,k。
第二行 n−1 个整数,第 i 个表示ai。
输出格式
一个整数,表示答案。
输入输出样例
输入 #1
4 0 1 2 3
输出 #1
6
输入 #2
4 1 1 2 3
输出 #2
3
说明/提示
样例解释 1:
样例 1,2 的图示均为以下图片:

不使用传送器直接走,答案为 6,可以证明这个是最小值。
样例解释 2:
在 3 处使用,传送到 4,答案为 3,可以证明这个是最小值。
数据范围:
对于所有数据,ai>0

解法:依旧是前缀和,但是可以减掉k段距离,那么就是减去这个区间里的最大值
题解:
for(int i=2;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
s[i]=s[i-1]+a[i];
for(int i=w;i<=n;i++)
mx=max(mx,s[i]-s[i-w]);
注意题目给的是点权,而前缀和是边权,所以要从2开始
P2367 语文成绩
题目背景
语文考试结束了,成绩还是一如既往地有问题。
题目描述
语文老师总是写错成绩,所以当她修改成绩的时候,总是累得不行。她总是要一遍遍地给某些同学增加分数,又要注意最低分是多少。你能帮帮她吗?
输入格式
第一行有两个整数 n,p,代表学生数与增加分数的次数。
第二行有 n 个数,a1∼an,代表各个学生的初始成绩。
接下来 p 行,每行有三个数,x,y,z,代表给第 x 个到第 y 个学生每人增加 z 分。
输出格式
输出仅一行,代表更改分数后,全班的最低分。
输入输出样例
输入 #1
3 2 1 1 1 1 2 1 2 3 1
输出 #1
2
说明/提示
对于 40% 的数据,有 n≤10的3次方。
对于 60% 的数据,有 n≤10的4次方。
对于 80% 的数据,有 n≤10的5次方。
对于 100% 的数据,有 n≤5×10的6次方,p≤n,学生初始成绩 ≤100,z≤100。
解法:这个就需要差分了,公式:a[i]=s[i+1]-s[i],a[l]+=1,a[r+1]-=1,只需要这三个公式就可以做这题了
题解:
for(int i=1;i<=n;i++)
{
cin>>s[i];
a[i]=s[i]-s[i-1];
}
for(int i=1;i<=p;i++)
{
int x,y,z;
cin>>x>>y>>z;
a[x]+=z;
a[y+1]-=z;
}
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+a[i];
mi=min(mi,s[i]);
}
错误:数据范围
P11853 [CSP-J2022 山东] 植树节
题目背景
受疫情影响,山东省取消了 CSP-J 2022 认证活动,并于次年三月重新命题,在省内补办比赛。
题目描述
植树节快要到了,学校要组织志愿者去给树苗浇水。
有一排树苗,编号依次是 0,1,2,…。
现有 n 个志愿者去给树苗浇水,第 i 个志愿者选定了一个区间 [ai,bi] ,表示第 i 个志愿者将 [ai,bi] 这一区间内的每一棵树都浇一次水。
如某个志愿者选择的浇水区间为 [4,9] ,表示他将给编号为 4,5,6,7,8,9 的树各浇水一次。
当所有的志愿者完成各自所选区间的浇水后,可能有些树苗被不同的志愿者浇水多次,也可能有的树苗一次也没被浇过水。
请你求出浇水最多的树苗被浇了多少次。
输入格式
第 1 行,一个整数 n ,表示志愿者的人数。
第 2 行到第 n+1 行,每行两个整数 ai,bi(i=0,1,2,…n−1),表示志愿者 i 选择的浇水区间。
输出格式
输出 1 行, 1 个整数,表示浇水最多的树苗被浇水的次数。
输入输出样例
输入 #1
4 0 2 2 4 1 4 6 7
输出 #1
3
输入 #2
4 1000000 1000000 1000000 1000000 0 1000000 1 1000000
输出 #2
4
说明/提示
数据范围
- 对于所有的数据: n≤105;0≤ai≤bi≤106。
| 测试点编号 | ai≤ | bi≤ | n≤ | 特殊性质 |
|---|---|---|---|---|
| 1,2,3 | 10的6次方 | 10的3次方 | 10的3次方 | 无 |
| 4,5,6,7 | 10的6次方 | 10的6次方 | 10的5次方 | 无 |
| 8 | 10的6次方 | 10的6次方 | 10的5次方 | ai=bi |
| 9 | 10的6次方 | 10的6次方 | 10的5次方 | ai=1,bi=10的3次方 |
| 10 | 10的6次方 | 10的6次方 | 10的5次方 | 无 |
附件下载
CSP-J2022入门组二轮补赛试题(山东).pdf1.58MB
解法:根上一题差不多,依旧是差分
题解:
for(int i=1;i<=n;i++)
{
int l,r;
cin>>l>>r;
a[l]++;
a[r+1]--;
}
s[0]=a[0];
for(int i=1;i<=1000000;i++)
s[i]=s[i-1]+a[i];
for(int i=0;i<=1000000;i++)
mx=max(mx,s[i]);
错误:最后两个循环的范围
P9094 [PA 2020] Mieszanie kolorów
题目描述
题目译自 PA 2020 Runda 1 Mieszanie kolorów
Byteasar 正准备给栅栏涂漆。他已经准备了 n 罐白色油漆,他把这些油漆排列成一排,从 1 到 n 编号。他想用这些油漆,但他不想把栅栏涂成白色。他委托了调色专家,调色专家有三种颜料:黄色、蓝色和红色。专家进行了 m 次操作,其中第 i 次操作是向编号在 li 到 ri 之间(包括两端)的所有罐子中加入某种颜料。
油漆的最终颜色取决于被添加到其中的颜料。添加的颜料按照下表和图示进行混合。
| 颜料 | 颜色 |
|---|---|
| 无 | 白色 |
| 黄色 | 黄色 |
| 蓝色 | 蓝色 |
| 红色 | 红色 |
| 黄色 + 蓝色 | 绿色 |
| 黄色 + 红色 | 橙色 |
| 蓝色 + 红色 | 紫色 |
| 黄色 + 蓝色 + 红色 | 棕色 |

Byteasar 想要给栅栏涂成一种颜色。思来想去,他选择了绿色,因为绿色代表了你常会在算法竞赛中看到的 Accepted。他想知道现在有多少罐油漆是绿色的,请帮他数数。
输入格式
第一行两个整数 n,m,分别表示油漆的罐数和专家进行的操作数。
接下来 m 行,每行三个整数 li,ri,ki,表示在第 i 次操作中向编号在 li 到 ri 之间(包括两端)的罐子中加入颜料。加入的颜料是黄色(ki=1),蓝色(ki=2)或红色(ki=3)中的一种。
输出格式
输出一行一个整数,表示在所有操作之后绿色油漆的罐数。
输入输出样例
输入 #1
9 5 2 8 1 4 5 2 6 7 3 5 6 2 1 2 2
输出 #1
3
说明/提示
样例 1 解释
操作结束后,这些油漆分别是蓝色、绿色、黄色、绿色、绿色、棕色、橙色、黄色和白色的。因此,只有三罐油漆是绿色。
数据范围
本题采用捆绑测试
对于 100% 的数据,保证 1≤n,m≤106,1≤li≤ri≤n,1≤ki≤3。
解法:定义三个a数组与差分数组进行操作,然后判断如果有黄色和蓝色并且没有红色就可以累加
题解:
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
if(z==1) a1[x]+=1,a1[y+1]-=1;
if(z==2) a2[x]+=1,a2[y+1]-=1;
if(z==3) a3[x]+=1,a3[y+1]-=1;
}
for(int i=1;i<=n;i++)
{
s1[i]=s1[i-1]+a1[i];
s2[i]=s2[i-1]+a2[i];
s3[i]=s3[i-1]+a3[i];
}
for(int i=1;i<=n;i++)
if(s1[i]!=0&&s2[i]!=0&&s3[i]==0) sum++;
玛雅这个题112个测试点吓哭了
1931

被折叠的 条评论
为什么被折叠?



