数组上的询问【前缀和】

来源:互联网 发布:幸福爱情网络歌曲歌词 编辑:程序博客网 时间:2024/06/06 20:49
Description

给出一个有N个元素的数组A,元素的值要么是1,要么是-1。

给出M次询问,每次询问的格式为:L, R,表示求S = A[L] + A[L+1] + ... + A[R]的值。若S 的值为0,输出"YES",否则输出"NO"。


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
5 5-1 1 -1 1 -11 12 33 52 51 5
Sample Output
NOYESNOYESNO

分析:第一眼看到了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");    }}  



原创粉丝点击