zoukankan      html  css  js  c++  java
  • Acwing 802. 区间和(下标离散化+vector+二分)

    地址:https://www.acwing.com/problem/content/description/804/

     

    一:

    本来想的是差分做,但是范围是不允许开这么大的数组的。l,r<=1e9

    所以考虑离散化。

    发现n只有1e5,n个加操作,m个L,R,最多用到n+L+R个区间,也就是3e5。所以开这么大就好了。

    vector具有去重函数,排序函数,所以考虑用它把所有输入的下标存起来,离散化成对应的vector下标值。

    比如:

    0    1     2

    12  200   10000

    下标12,200,10000可以由0,1,2代替。

    而对于一个离散前的下标,在vector里寻找时二分即可。

    二:

    代码思路:

    vector<int>alls;   //存所有下标
    vector<PII>query,add;  //add存n个操作,x-c。query存m个询问操作:L--R

    int a[maxn]; //下标离散后的各个位置的值

    int s[maxn];//前缀和

    1:n个操作,x,c。alls,add存取

    2:m个操作,L,R。alls,query存取

    3:alls排序,去重

    4:a[]把离散化的下标+c

    5:前缀和

    6:遍历query里的每一组L-R,找到它们在alls里离散化后的下标,前缀和即可。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<set>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PII;
    const int maxn=3e5+10,maxn2=31*maxn;//maxn·­±¶ 
    int n,m;
    vector<int>alls;
    vector<PII>query,add;
    int a[maxn],s[maxn];
    int find(int x)
    {
        int l=0,r=alls.size()-1;
        while(l<r)
        {
            int md=l+r>>1;
            if(alls[md]>=x)
                r=md;
            else
                l=md+1;
        }
        return r+1;
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
            int x,c;
            cin>>x>>c;
            add.push_back({x,c});
            alls.push_back(x);
        }
        for(int i=1;i<=m;i++)
        {
            int l,r;
            cin>>l>>r;
            query.push_back({l,r});
            alls.push_back(l);
            alls.push_back(r);
        }
        sort(alls.begin(),alls.end());
        alls.erase(unique(alls.begin(),alls.end()),alls.end());
        for(auto item : add)
        {
            int x=find(item.first);
            a[x]+=item.second;
        }
        for(int i=1;i<=alls.size();i++)
        {
            s[i]=s[i-1]+a[i];
        }
        for(auto item : query)
        {
            int l = find(item.first),r=find(item.second);
            cout<<s[r]-s[l-1]<<endl;
        }
    }
  • 相关阅读:
    EC++学习笔记(五) 实现
    EC++学习笔记(三) 资源管理
    EC++学习笔记(一) 习惯c++
    EC++学习笔记(六) 继承和面向对象设计
    STL学习笔记(三) 关联容器
    STL学习笔记(一) 容器
    背包问题详解
    EC++学习笔记(二) 构造/析构/赋值
    STL学习笔记(四) 迭代器
    常用安全测试用例
  • 原文地址:https://www.cnblogs.com/liyexin/p/13970121.html
Copyright © 2011-2022 走看看