值域大,个数小
两个问题
- 重复元素 > 去重
- 快速映射 > 二分
模板
vector<int> alls; // 存储所有待离散化的值sort(alls.begin(), alls.end()); // 将所有值排序alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重复元素// 二分求出x对应的离散化的值int find(int x) // 找到第一个大于等于x的位置{int l = 0, r = alls.size() - 1;while (l < r){int mid = l + r >> 1;if (alls[mid] >= x) r = mid;else l = mid + 1;}return r + 1; // 映射到1, 2, ...n}
运用
//离散化,让大的数变成小的//用vector储存大的数,然后处理大的数a的时候,在vector中找到a,返回vector的下标x//在定义一个数组,a => x;处理a[x]即可#include <iostream>#include <cstring>#include <algorithm>#include <vector>using namespace std;typedef long long LL;typedef pair<int,int> PII;vector<int> alls;vector<PII> add,query;int a[300010],s[300010];int find(int x) // 找到x{int l= 0,r=alls.size()-1;while(l<r){int mid = l+r >> 1;if(alls[mid]>=x) r=mid; //找x的最左边else l=mid+1;}return r+1; // 方便前缀和}int main(){int n,m;cin>>n>>m;for(int i=0;i<n;i++){int x,c;cin>>x>>c;add.push_back({x,c});alls.push_back(x);}for(int i=0;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);int r = find(item.second);cout<<s[r]-s[l-1]<<endl;}return 0;}
区间合并

// 将所有存在交集的区间合并void merge(vector<PII> &segs){vector<PII> res; //先定义一个新的PIIsort(segs.begin(), segs.end()); //对于pair的排序,先按first,若相等,再按second;int st = -2e9, ed = -2e9;for (auto seg : segs) // 新的区间,分开的if (ed < seg.first){if (st != -2e9) res.push_back({st, ed});st = seg.first, ed = seg.second;}else ed = max(ed, seg.second); //有相交的if (st != -2e9) res.push_back({st, ed}); //再把第13行的放进去segs = res; //更新}
