离散化-区间和

假定有一个无限长的数轴,数轴上每个坐标上的数都是0。

现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。

近下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。

输入格式

第一行包含两个整数n和m。

接下来 n 行,每行包含两个整数x和c。

再接下里 m 行,每行包含两个整数l和r。

输出格式

共m行,每行输出一个询问中所求的区间内数字和。

数据范围

−109≤x≤109−109≤x≤109,
1≤n,m≤1051≤n,m≤105,
−109≤l≤r≤109−109≤l≤r≤109,
−10000≤c≤10000−10000≤c≤10000

输入样例:

3 3
1 2
3 6
7 5
1 3
4 6
7 8

输出样例:

8
0
5

离散化的本质,是映射,将间隔很大的点,映射到相邻的数组元素中。减少对空间的需求,也减少计算量。 

离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。

 如果开数组,那么需要的数组就太大了,可以用合适大小的数组将已更改值的下标存入,按顺序存,这样节省空间。

所以要进行排序,然后去重;具体看代码;

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int n,sum[N];
typedef struct{
    int num;
    int val;
}pill;
pill a[N];
//排序也可用sort 
void quick_sort(int l,int r,pill q[]){
    if(l >= r) return ;
    int temp = q[l + r >> 1].num;
    int i = l - 1,j = r + 1;
    while(i < j){
        do i++;while(q[i].num < temp);
        do j--;while(q[j].num > temp);
        if(i < j){
            // pill t = q[i];
            // q[i] = q[j];
            // q[j] = t;
            swap(q[i],q[j]);
        }
    }
    quick_sort(l,j,a);quick_sort(j + 1,r,a);
}
//寻找大于x的最小下标,也就是更改的第一个数,没更改就是0; 
int findl(int x){
    int l = 1,r = n;
    while(l < r){
        int mid = l + r >> 1;
        if(a[mid].num >= x) r = mid;
        else l = mid + 1;
    }
    if(x <= a[l].num)
    return l;
    else return n + 1;
}
//寻找小于r的最大值,也就是在区间[l,r]找已更改的上线; 
int findr(int x){
    int l = 1,r = n;
    while(l < r){
        int mid = l + r + 1 >> 1;
        if(a[mid].num <= x) l = mid;
        else r = mid - 1;
    }
    if(x >= a[l].num)
    return l;
    else return 0;
}
int main(){
    int m;
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++)scanf("%d%d",&a[i].num,&a[i].val);
    quick_sort(1,n,a);
    //讲相同的去掉,并把数组变小; 
    int j = 1;
    for(int i = 2; i <= n; i++){
        if(a[i].num > a[i - 1].num)a[++j] = a[i];
        else a[j].val += a[i].val; 
    }
    n = j;
    //前缀和; 
    for(int i = 1; i <= j; i++) sum[i] = sum[i - 1] + a[i].val;
    
    while(m--){
        int l,r;
        scanf("%d%d",&l,&r);
        l = findl(l),r = findr(r);
        printf("%d\n",sum[r] - sum[l - 1]);
    }
    //for(int i = 1; i <=n; i++)printf("%d ",a[i].num);
    return 0;
}
发布了97 篇原创文章 · 获赞 3 · 访问量 9426

猜你喜欢

转载自blog.csdn.net/foolishpichao/article/details/101178750