[bzoj2850]2850: 巧克力王国

2850: 巧克力王国

Time Limit: 60 Sec   Memory Limit: 512 MB
[ Submit][ Status][ Discuss]

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

5
0
4

HINT

1 <= n, m <= 50000,1 <= 10^9,-10^9 <= a, b, x, y <= 10^9。


 


Source

我对kdtree不到位,只能看模板
此题据说不是kdtree,但是能过
输入不是lld竟然WA了
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N = 50000 + 5;
typedef long long ll;
ll A,B,C,ans;
int F,n,m,root;
struct node{
	int d[2],mx[2],mn[2],v,l,r; ll sum;
	int& operator[]( int x ){return d[x];}
	friend bool operator<(node a,node b){ return a[F] < b[F]; }
}p[N];
bool check( int x, int y ){ return A*x+B*y < C; }
int cal( node x ){
	int res=0;
	res += check(x.mn[0],x.mn[1]);
	res += check(x.mx[0],x.mn[1]);
	res += check(x.mn[0],x.mx[1]);
	res += check(x.mx[0],x.mx[1]);
	return res;
}
struct kdtree{
	node t[N];
	void update( int k ){
		int l = t[k].l, r = t[k].r;
		for( int i = 0; i < 2; i++ ){
			t[k].mn[i] = t[k].mx[i] = t[k][i];
			if(l) t[k].mn[i] = min(t[k].mn[i],t[l].mn[i]);
			if(l) t[k].mx[i] = max(t[k].mx[i],t[l].mx[i]);
			if(r) t[k].mn[i] = min(t[k].mn[i],t[r].mn[i]);
			if(r) t[k].mx[i] = max(t[k].mx[i],t[r].mx[i]);
		}
		t[k].sum = t[l].sum + t[r].sum + t[k].v;
	}
	int build( int l, int r, int now ){
		F = now; int mid = (l+r)>>1;
		nth_element(p+l,p+mid,p+r+1);
		t[mid] = p[mid];
		if( l < mid ) t[mid].l = build( l, mid-1, now^1 );
		if( r > mid ) t[mid].r = build( mid+1, r, now^1 );
		update(mid); return mid;
	}
	void query( int k ){
		int l = t[k].l, r = t[k].r;
		if( check(t[k][0],t[k][1]) ) ans += t[k].v;
		int tl = 0, tr = 0;
		if(l) tl = cal(t[l]);
		if(r) tr = cal(t[r]);
		if( tl == 4 ) ans += t[l].sum;
		else if( tl ) query(l);
		if( tr == 4 ) ans += t[r].sum;
		else if( tr ) query(r);
	}
}kd;
int main(){
	scanf("%d%d", &n, &m);
	for( int i = 1; i <= n; i++ ) scanf("%lld%lld%lld", &p[i][0], &p[i][1], &p[i].v);
	root = kd.build( 1, n, 0 );
	while( m-- ){
		scanf("%lld%lld%lld", &A, &B, &C);
		ans = 0; kd.query(root);
		printf("%lld\n", ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值