LG4475 巧克力王国

巧克力王国

巧克力王国里的巧克力都是由牛奶和可可做成的。但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力。

对于每一块巧克力,我们设 x 和 y 为其牛奶和可可的含量。由于每个人对于甜的程度都有自己的评判标准,所以每个人都有两个参数 a 和 b ,分别为他自己为牛奶和可可定义的权重, 因此牛奶和可可含量分别为 x 和 y 的巧克力对于他的甜味程度即为 ax+by。而每个人又有一个甜味限度 c ,所有甜味程度大于等于 c 的巧克力他都无法接受。每块巧克力都有一个美味值 h 。

现在我们想知道对于每个人,他所能接受的巧克力的美味值之和为多少。

CQzhangyu的题解

看起来ax+by<c挺难搞,但其实只要改一改KDtree的估价函数就好了,具体见代码

其实就是判断一下矩形的四个角是否在半平面内。

注意:别忘了a,b,x,y可以是负数,负负能得正!

据说复杂度是每次询问期望√n,但我感觉这东西不靠谱。

struct kd{
	int ls,rs,sm[2],sn[2],v[2];
	ll sum,s;
	kd(){}
	kd(int a,int b,int c){ls=rs=0,sm[0]=sn[0]=v[0]=a,sm[1]=sn[1]=v[1]=b,s=sum=c;}
}t[100001];
int n,m,D,root;
ll A,B,C;
bool cmp(co kd&a,co kd&b){
	return a.v[D]<b.v[D];
}
void pushup(int x,int y){
	for(int i=0;i<2;++i)
		t[x].sm[i]=max(t[x].sm[i],t[y].sm[i]),t[x].sn[i]=min(t[x].sn[i],t[y].sn[i]);
	t[x].sum+=t[y].sum;
}
int build(int l,int r,int d){
	if(l>r) return 0;
	int mid=(l+r)>>1;
	D=d;
	nth_element(t+l,t+mid,t+r+1,cmp);
	t[mid].ls=build(l,mid-1,d^1),t[mid].rs=build(mid+1,r,d^1);
	if(t[mid].ls) pushup(mid,t[mid].ls);
	if(t[mid].rs) pushup(mid,t[mid].rs);
	return mid;
}
int check(int x){
	int re=0;
	re+=A*t[x].sn[0]+B*t[x].sn[1]<C;
	re+=A*t[x].sm[0]+B*t[x].sn[1]<C;
	re+=A*t[x].sm[0]+B*t[x].sm[1]<C;
	re+=A*t[x].sn[0]+B*t[x].sm[1]<C;
	return re;
}
ll query(int x){
	if(!x||!check(x)) return 0;
	if(check(x)==4) return t[x].sum;
	ll re=0;
	if(A*t[x].v[0]+B*t[x].v[1]<C) re+=t[x].s;
	re+=query(t[x].ls)+query(t[x].rs);
	return re;
}
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	read(n),read(m);
	int a,b,c;
	for(int i=1;i<=n;++i){
		read(a),read(b),read(c);
		t[i]=kd(a,b,c);
	}
	root=build(1,n,0);
	for(int i=1;i<=m;++i){
		read(A),read(B),read(C);
		printf("%lld
",query(root));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/autoint/p/10407044.html