数组上的询问【前缀和】
Description
Input
第1行:两个整数N和M(1<=N, M <=100000)
第2行:N个空格分开的整数,表示数组的各个元素,保证只含1和-1
接下来M行,每行两个整数L,R(1 <=L <= R <=N),表示每个询问的左右端点
Output
共M行,对每个询问,若和为0,输出"YES",否则输出"NO"
Sample Input
Sample Output
给出一个有N个元素的数组A,元素的值要么是1,要么是-1。
给出M次询问,每次询问的格式为:L, R,表示求S = A[L] + A[L+1] + ... + A[R]的值。若S 的值为0,输出"YES",否则输出"NO"。
第2行:N个空格分开的整数,表示数组的各个元素,保证只含1和-1
接下来M行,每行两个整数L,R(1 <=L <= R <=N),表示每个询问的左右端点
5 5 -1 1 -1 1 -1 1 1 2 3 3 5 2 5 1 5
NO YES NO YES NO
分析:第一眼看到了l,r,还以为是二分,然后仔细读完题目,觉得好简单,果断开始模拟,交上去之后才发现
然后开始想怎么节省时间,不可能再模拟了,此时我想到的居然是记忆化递归,扶额...好吧,我确实没想到其他东西了,又不是搜索,深搜超时改广搜,于是去问老师,然后得解。
其实就是再另外找一个数组存和,举个例子
数组a来存储那个数组,s来存和,可以:
s[1]=a[1];
s[2]=s[1]+a[2];(前2数之和)
s[3]=s[2]+a[3];(前3数之和)
s[4]=s[3]+a[4];(前4数之和)
我们如果要求2~5,只用将s[5]-s[2-1]即可,s[5]-s[1]=a[1]+a[2]+a[3]+a[4]+a[5]-a[1]=a[2]+a[3]+a[4]+a[5]
是不是很神奇?所以只要学了知识,就能完成许多神奇的事情,知识改变命运 我是说了些什么心灵鸡汤么
如果还没有看懂的话,我们再举个例子
我们如果要求3~6,只用将s[6]-s[3-1]即可,s[6]-s[2]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]-a[1]-a[2]=a[2]+a[3]+a[4]+a[5]+a[6]
那么,代码奉上:(就不写注释啦,前面的看懂之后应该分分钟秒杀啦 //分分钟还秒杀?)
#include<cstdio>
#include<cmath>
int n,m,num[100005],s[100005],l,r;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
for(int i=1;i<=n;i++)
s[i]=s[i-1]+num[i];
for(int i=1;i<=m;i++)
{
scanf("%d %d",&l,&r);
if(s[r]-s[l-1]) printf("NO\n");
else printf("YES\n");
}
}
转载请注明出处,有疑问欢迎探讨
博主邮箱 2775182058@qq.com