题目链接: 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;
}