地址: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; } }