区间和
假定有一个无限长的数轴,数轴上每个坐标上的数都是0。
现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。
接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。
输入格式:
第一行包含两个整数n和m。
接下来 n 行,每行包含两个整数x和c。
再接下里 m 行,每行包含两个整数l和r。
输出格式:
共m行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109,
1≤n,m≤105,
−109≤l≤r≤109,
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
万题皆可暴力,不同的是暴力的时间空间复杂度感人qwq。
暴力做法:空间复杂度O(109),时间复杂度O(1014)。
但是NB的大神创造出NB的做法,使得时间空间复杂度大大降低。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=100010;
struct digit{int num,val;}a[MAXN];
int n,m,l,r,b[MAXN];
bool cmp(digit x,digit y){return x.num<y.num;}
int findl(int x){
int l=1,r=n;
while(l<r){
int mid=l+r>>1;
if(a[mid].num<x) l=mid+1;
else r=mid;
}
if(a[l].num>=x) return l;
else return n+1;
}
int findr(int x){
int l=1,r=n;
while(l<r){
int mid=l+r+1>>1;
if(a[mid].num>x) r=mid-1;
else l=mid;
}
if(a[r].num<=x) return r;
else return 0;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].num,&a[i].val);
sort(a+1,a+n+1,cmp);//快速排序
int j=1;
for(int i=2;i<=n;i++){//双指针去重
if(a[j].num==a[i].num) a[j].val+=a[i].val;
else a[++j]=a[i];
}
n=j;
for(int i=1;i<=n;i++) b[i]=b[i-1]+a[i].val;//前缀和
while(m--){
scanf("%d%d",&l,&r);
l=findl(l);r=findr(r);//二分查找
printf("%d\n",b[r]-b[l-1]);
}
return 0;
}
我们为什么要打代码?当然是为了应用了!
我们如何处理这么复杂的问题?当然是打代码了!