【bzoj2850】巧克力王国 KD-tree

题目描述

巧克力王国里的巧克力都是由牛奶和可可做成的。但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力。对于每一块巧克力,我们设x和y为其牛奶和可可的含量。由于每个人对于甜的程度都有自己的评判标准,所以每个人都有两个参数a和b,分别为他自己为牛奶和可可定义的权重,因此牛奶和可可含量分别为x和y的巧克力对于他的甜味程度即为ax + by。而每个人又有一个甜味限度c,所有甜味程度大于等于c的巧克力他都无法接受。每块巧克力都有一个美味值h。现在我们想知道对于每个人,他所能接受的巧克力的美味值之和为多少

输入

第一行两个正整数n和m,分别表示巧克力个数和询问个数。接下来n行,每行三个整数x,y,h,含义如题目所示。再接下来m行,每行三个整数a,b,c,含义如题目所示。

输出

输出m行,其中第i行表示第i个人所能接受的巧克力的美味值之和。

样例输入

3 3
1 2 5
3 1 4
2 2 1
2 1 6
1 3 5
1 3 7

样例输出

5
0
4



题解

KD-tree

朴素的n^2暴力显然会TLE,我们来优化这个过程。

题目要求出某条直线下方的所有点的权值和,不过看做直线并没有什么用。

考虑,如果能够使得某一些点都符合条件或都不符合条件,那么就可以降低查找的时间。

所以我们使用KD-tree来维护平面上的点。查询时,判断一下区域内的点是否都满足条件或都不满足条件,可以减去大量时间。

不过时间复杂度上界貌似还是O(n^2)的

估价函数需要分4种情况讨论

#include <cstdio>
#include <algorithm>
#define N 50010
using namespace std;
typedef long long ll;
struct data
{
	ll p[2] , v , maxn[2] , minn[2] , sum;
	int c[2];
}a[N];
int d , root;
bool cmp(data a , data b)
{
	return a.p[d] == b.p[d] ? a.p[d ^ 1] < b.p[d ^ 1] : a.p[d] < b.p[d];
}
void pushup(int k , int x)
{
	a[k].maxn[0] = max(a[k].maxn[0] , a[x].maxn[0]);
	a[k].maxn[1] = max(a[k].maxn[1] , a[x].maxn[1]);
	a[k].minn[0] = min(a[k].minn[0] , a[x].minn[0]);
	a[k].minn[1] = min(a[k].minn[1] , a[x].minn[1]);
	a[k].sum += a[x].sum;
}
int build(int l , int r , int now)
{
	int mid = (l + r) >> 1;
	d = now , nth_element(a + l , a + mid , a + r + 1 , cmp);
	a[mid].maxn[0] = a[mid].minn[0] = a[mid].p[0];
	a[mid].maxn[1] = a[mid].minn[1] = a[mid].p[1];
	a[mid].sum = a[mid].v;
	if(l < mid) a[mid].c[0] = build(l , mid - 1 , now ^ 1) , pushup(mid , a[mid].c[0]);
	if(r > mid) a[mid].c[1] = build(mid + 1 , r , now ^ 1) , pushup(mid , a[mid].c[1]);
	return mid;
}
int getdis(int k , ll x , ll y , ll z)
{
	if(x >= 0 && y >= 0)
	{
		if(x * a[k].maxn[0] + y * a[k].maxn[1] < z) return 1;
		if(x * a[k].minn[0] + y * a[k].minn[1] >= z) return -1;
	}
	else if(x < 0 && y >= 0)
	{
		if(x * a[k].minn[0] + y * a[k].maxn[1] < z) return 1;
		if(x * a[k].maxn[0] + y * a[k].minn[1] >= z) return -1;
	}
	else if(x >= 0 && y < 0)
	{
		if(x * a[k].maxn[0] + y * a[k].minn[1] < z) return 1;
		if(x * a[k].minn[0] + y * a[k].maxn[1] >= z) return -1;
	}
	else
	{
		if(x * a[k].minn[0] + y * a[k].minn[1] < z) return 1;
		if(x * a[k].maxn[0] + y * a[k].maxn[1] >= z) return -1;
	}
	return 0;
}
ll query(int k , ll x , ll y , ll z)
{
	int t = getdis(k , x , y , z);
	if(t == 1) return a[k].sum;
	if(t == -1) return 0;
	ll ans = 0;
	if(a[k].p[0] * x + a[k].p[1] * y < z) ans += a[k].v;
	if(a[k].c[0]) ans += query(a[k].c[0] , x , y , z);
	if(a[k].c[1]) ans += query(a[k].c[1] , x , y , z);
	return ans;
}
int main()
{
	int n , m , i;
	ll x , y , z;
	scanf("%d%d" , &n , &m);
	for(i = 1 ; i <= n ; i ++ ) scanf("%lld%lld%lld" , &a[i].p[0] , &a[i].p[1] , &a[i].v);
	root = build(1 , n , 0);
	while(m -- ) scanf("%lld%lld%lld" , &x , &y , &z) , printf("%lld\n" , query(root , x , y , z));
	return 0;
}
时间: 2024-08-26 19:01:40

【bzoj2850】巧克力王国 KD-tree的相关文章

bzoj2850巧克力王国*

bzoj2850巧克力王国 题意: n个巧克力,每个有牛奶含量,可可含量和美味值.m个人,每个有三个权值a,b,c,如果某个巧克力的牛奶含量*a+可可含量*b<c就可以接受.问每个人能接受的巧克力美味值之和.n,m≤50000. 题解: 对所有巧克力建kd树,树上节点除了维护子树横纵坐标最大最小值还要维护子树美味值之和.在查询时如果估价得出这个子树的牛奶含量最大值乘a+可可含量最大值*b小于c则整棵子树都能接受,否则只要该子树可能有机会存在可接受巧克力就遍历这棵子树. 代码: 1 #includ

【kd-tree】bzoj2850 巧克力王国

分四种情况讨论:a,b>=0 a,b<0 a>=0,b<0 a<0,b>=0 然后每次检验是否进入一个矩形框 或者 是否直接利用这个矩形框的答案 仅仅利用两个对角的坐标进行更新即可. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; #define N 50001 #define INF 214

BZOJ2850 巧克力王国

题意:给定一堆点,每个点有权值,每次求在直线$Ax + By + C = 0$下的点的权值和 KD树维护一下二维区间内的点权和就好恩...建树复杂度$O(n * logn)$,单次查询时间$O(\sqrt{n})$ 1 /************************************************************** 2 Problem: 2850 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:155

【BZOJ2850】巧克力王国 KDtree

[BZOJ2850]巧克力王国 Description 巧克力王国里的巧克力都是由牛奶和可可做成的.但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜 欢过于甜的巧克力.对于每一块巧克力,我们设x和y为其牛奶和可可的含量.由于每个人对于甜的程度都有自己的 评判标准,所以每个人都有两个参数a和b,分别为他自己为牛奶和可可定义的权重,因此牛奶和可可含量分别为x 和y的巧克力对于他的甜味程度即为ax + by.而每个人又有一个甜味限度c,所有甜味程度大于等于c的巧克力他都 无法接受.每块巧克力都

[转载]kd tree

[本文转自]http://www.cnblogs.com/eyeszjwang/articles/2429382.html k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树

k-d tree算法详解

k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 1.应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树就是其中一种. 索引结构中相似性查询有两种基本的方式:一种是范围查询(range searches),另一种是K近邻查询

k-d tree算法

k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k-d树.而特征点匹配实际上就是一个通过距离函数在高维矢量之间进行相似性检索的问题.针对如何快速而准确地找到查询点的近邻,现在提出了很多高维空间索引结构和近似查询的算法,k-d树就是其中一种. 索引结构中相似性查询有两种基本的方式:一种是范围查询(range searches),另一种是K近邻查询(K

k-d Tree in TripAdvisor

Today, TripAdvisor held a tech talk in Columbia University. The topic is about k-d Tree implemented in TripAdvisor  to efficiently search MASSIVE location tree. Problem Millions of locations, it's tough to perform Nearest Neighbor Search. Solution Us

Google interview question: k-nearest neighbor (k-d tree)

Question: You are given information about hotels in a country/city. X and Y coordinates of each hotel are known. You need to suggest the list of nearest hotels to a user who is querying from a particular point (X and Y coordinates of the user are giv