离散化
有些情况下,数字的值的绝对大小并不重要,而相对大小很重要。“离散化”是用数字的相对值代替它们的绝对值。
把分布广而稀疏的数据转化为密集分布,从而能够让算法更快速,更省空间地处理。
离散化三步骤:
- 排序
- 去重
- 映射到0,1,2,3这些点,通过二分法进行处理
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。
接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n和 m。
接下来 n 行,每行包含两个整数 x 和 c。
再接下来 m 行,每行包含两个整数 l 和 r。
输出格式
共 m 行,每行输出一个询问中所求的区间内数字和。
数据范围
−
1
0
9
≤
x
≤
1
0
9
−10^9≤x≤10^9
−109≤x≤109,
1
≤
n
,
m
≤
1
0
5
1≤n,m≤10^5
1≤n,m≤105,
−
1
0
9
≤
l
≤
r
≤
1
0
9
−10^9≤l≤r≤10^9
−109≤l≤r≤109,
−
10000
≤
c
≤
10000
−10000≤c≤10000
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
typedef pair<int,int>PII;
vector<int>alls;
vector<PII>add,query;
int s[N],a[N];
int find(int x)
{
int l=0,r=alls.size()-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(alls[mid]<=x)l=mid+1;
else r=mid-1;
}
return r+1;
}
signed main()
{
int n,x,c,m,l,r;cin>>n;cin>>m;
while(n--)
{
cin>>x>>c;
add.push_back({x,c});
alls.push_back(x);
}
while(m--)
{
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)//用auto遍历时是遍历数组内的所有元素,如果不是遍历所有,就不用这种
{
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;
}
区间合并
给定 n 个区间 [ l i , r i l_i,r_i li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3] 和 [2,6] 可以合并为一个区间 [1,6]。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
1 ≤ n ≤ 100000,
−
1
0
9
≤
l
i
≤
r
i
≤
1
0
9
−10^9 ≤ l_i ≤ r_i ≤ 10^9
−109≤li≤ri≤109
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int N=100010;
int n;
vector<PII>segs;
void merge(vector<PII>&segs)
{
vector<PII>res;
sort(segs.begin(),segs.end());//要先按区间左端点排序
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});//把最后一个点加进去
segs=res;//将res赋给segs
}
int main()
{
cin>>n;int l,r;
while(n--)
{
cin>>l>>r;
segs.push_back({l,r});
}
merge(segs);
cout<<segs.size();
return 0;
}