离线二维数点模板

题目

离线二维数点模板

时间复杂度:\(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;
}
posted @ 2026-08-18 07:38  decentz  阅读(11)  评论(0)    收藏  举报