[BZOJ2850]巧克力王国

本文介绍了KD-Tree的数据结构及其构建与查询方法。KD-Tree通过在不同维度上选择中位数进行分割来组织数据点,适用于高维空间中的范围查询。文中还提供了一个具体的实现案例。

今天才学了一下kd-tree,感觉它本质上就是个暴力...

kd-tree用于维护高维空间中的一些点,它在建树时轮流在每一维坐标中选取中位数作为分割依据,最后形成一个树形结构

维护一个节点所管辖的坐标范围,然后查询就跟线段树差不多了

它维护$k$维空间时的范围查询时间复杂度是$O\left(kn^{1-\frac1k}\right)$,证明咕咕咕

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
struct candy{
	int x,y,h;
}d[50010];
struct kd{
	int l,r,mxx,mnx,mxy,mny,x,y,h;
	ll s;
	kd operator=(candy c){
		x=c.x;
		y=c.y;
		h=c.h;
		return*this;
	}
}t[50010];
bool cmpx(candy a,candy b){return a.x<b.x;}
bool cmpy(candy a,candy b){return a.y<b.y;}
void pushup(int x){
	t[x].mxx=t[x].mnx=t[x].x;
	t[x].mxy=t[x].mny=t[x].y;
	int l=t[x].l,r=t[x].r;
	if(l){
		t[x].mxx=max(t[x].mxx,t[l].mxx);
		t[x].mnx=min(t[x].mnx,t[l].mnx);
		t[x].mxy=max(t[x].mxy,t[l].mxy);
		t[x].mny=min(t[x].mny,t[l].mny);
	}
	if(r){
		t[x].mxx=max(t[x].mxx,t[r].mxx);
		t[x].mnx=min(t[x].mnx,t[r].mnx);
		t[x].mxy=max(t[x].mxy,t[r].mxy);
		t[x].mny=min(t[x].mny,t[r].mny);
	}
	t[x].s=t[l].s+t[r].s+t[x].h;
}
int build(int l,int r,int f){
	int mid=(l+r)>>1;
	nth_element(d+l,d+mid,d+r+1,f?cmpx:cmpy);
	t[mid]=d[mid];
	if(l<mid)t[mid].l=build(l,mid-1,f^1);
	if(mid<r)t[mid].r=build(mid+1,r,f^1);
	pushup(mid);
	return mid;
}
int a,b,c;
int check(ll x,ll y){return a*x+b*y<c;}
int check(kd u){return check(u.mnx,u.mny)+check(u.mxx,u.mny)+check(u.mnx,u.mxy)+check(u.mxx,u.mxy);}
ll query(int x){
	if(check(t[x])==4)return t[x].s;
	ll s=check(t[x].x,t[x].y)*t[x].h;
	if(check(t[t[x].l]))s+=query(t[x].l);
	if(check(t[t[x].r]))s+=query(t[x].r);
	return s;
}
int main(){
	int n,m,i,rt;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)scanf("%d%d%d",&d[i].x,&d[i].y,&d[i].h);
	rt=build(1,n,0);
	while(m--){
		scanf("%d%d%d",&a,&b,&c);
		printf("%lld\n",query(rt));
	}
}

转载于:https://www.cnblogs.com/jefflyy/p/9220011.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值