AYIT Online Judge 贪吃LP(前缀和思想实质)

题目链接http://acm.ayit.edu.cn:81/problem/154
时间限制:1s    内存限制:256M    满分: 100分
题目描述
LP贪吃众所周知,从他进入实验室的n天里,总共买了m次零食,每次买b包一样的零食,但是这m次买的零食都不相同。
从买这种零食这天起,这种零食每天都只吃一包,直到吃完为止。
ZHZH对LP这种偷偷一个人吃的行为忍无可忍,决定向学长打小报告。
但是他需要确切的证据,所以他决定统计K组数据,每组数据是LP从第x天到第y天内吃了多少种零食。
但是他太懒了决定请你来做。
输入描述
数据包含多组输入
第一行三个整数:n m k
然后是m行,每一行两个数a和b,a表示买零食那天,b表示每次买的零食包数。
最后是k行,每一行两个数 x,y。
输出描述
输出一行包含k个数,相邻两个数用一个空格隔开。
下面有一个样例:
样例输入

3 3 1
1 3
2 2
3 1
1 3

3 3 3
1 1
2 1
3 1
1 1
2 2
3 3

样例输出

3
1 1 1

数据范围
保证 $ 1<=n,m,(a+b)<=2000000,1<=x<=y<=n,k大于0并且不大于200000

分析
对于每次询问的区间[x,y],如果知道从第一天到第x-1天的种类和
以及从第一天到第y天的种类和,就可以通过后者减去前者。
开两个数组a和b,分别对应区间的起始和结束。进行前缀和。
前缀和的思想:前者对后者造成影响
最后给定区间[x,y],求其这个区间的种类数。就用a[y]-b[x-1]来表示。
代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MN=2000010;
int a[MN],b[MN],c[MN];
int main()
{
    int n,m,k,t1,t2;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d",&t1,&t2);
            if(t2>0)
            {
                a[t1]+=1;
                b[t1+t2-1]+=1;/*从t1这一天开始吃,到t1+t2-1这一天结束*/
            }
        }
        for(int i=1; i<=n; i++)
        {
            a[i]+=a[i-1];
            b[i]+=b[i-1];
        }
        int flag=0;
        for(int i=1; i<=k; i++)
        {
            scanf("%d%d",&t1,&t2);
            c[i]=a[t2]-b[t1-1];/*a[t2]表示从1到t2天一共吃了多少种零食,这个地方需要注意是a[t2]-b[t1-1],可以自己好好想一下*/
        }
        for(int i=1; i<k; i++)
            printf("%d ",c[i]);
        printf("%d\n",c[k]);
    }
    return 0;
}
发布了165 篇原创文章 · 获赞 6 · 访问量 5042

猜你喜欢

转载自blog.csdn.net/lylzsx20172018/article/details/103710955