离线二维数点模板
离线二维数点模板
时间复杂度:\(O((n+m)\log V)\),(\(V\) 是值域大小)
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int n,m,a[N],tr[N],ans[N];//a:原序列,tr:树状数组,ans:每个询问的答案
struct node{
int x,val,id;//x:询问的数值上界,val:正负号(±1),id:询问编号
};
vector<node> vec[N];//vec[i]存所有“右端点为i”的查询信息
int lowbit(int x){return x&-x;}
void add(int x){//单点加:将数值为x的元素个数+1
while(x<=2e6){
tr[x]++;
x+=lowbit(x);
}
}
int query(int x){//查询当前已加入的元素中,数值<=x的个数
int sum=0;
while(x){
sum+=tr[x];
x-=lowbit(x);
}
return sum;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1,l,r,x;i<=m;i++){//离线处理查询将每个[l,r]拆成[1,r]和[1,l-1]的差
cin>>l>>r>>x;
vec[l-1].push_back({x,-1,i});//在l-1处累加-1的贡献
vec[r].push_back({x,1,i});//在r处累加+1的贡献
}
for(int i=1;i<=n;i++){//按位置顺序扫描,同时维护树状数组
add(a[i]);//将a[i]加入
for(int j=0;j<(int)vec[i].size();j++){//处理所有右端点为i的查询
ans[vec[i][j].id]+=vec[i][j].val*query(vec[i][j].x);//得到[l,r]内≤x的个数
}
}
for(int i=1;i<=m;i++){
cout<<ans[i]<<'\n';
}
return 0;
}

浙公网安备 33010602011771号