BZOJ 2850: 巧克力王国 KDtree + 估价函数
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个人所能接受的巧克力的美味值之和。
题解: 关键还是在于启发式估价函数.
如果当前点所维护的矩形的极限大的 $ax+by$ 小于等于 $c$ ,说明全部符合要求.
如果极限小值都不符合要求,说明整个矩形都不合法,返回 $0$ 即可.
#include<bits/stdc++.h> #define maxn 100000 #define inf 1000000008 #define mid ((l+r)>>1) #define ll long long #define lson (t[x].ch[0]) #define rson (t[x].ch[1]) using namespace std; void setIO(string s) { string in=s+".in"; freopen(in.c_str(),"r",stdin); } int n,Q,d; ll C, A[4]; struct Node { int minv[2],maxv[2],p[2],ch[2]; ll sumv,w; }t[maxn]; bool cmp(Node a,Node 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 x,int y) { t[x].minv[0]=min(t[x].minv[0], t[y].minv[0]); t[x].maxv[0]=max(t[x].maxv[0], t[y].maxv[0]); t[x].minv[1]=min(t[x].minv[1], t[y].minv[1]); t[x].maxv[1]=max(t[x].maxv[1], t[y].maxv[1]); t[x].sumv+=t[y].sumv; } int build(int l,int r,int o) { d=o; nth_element(t+l,t+mid,t+1+r,cmp); t[mid].minv[0]=t[mid].maxv[0]=t[mid].p[0]; t[mid].minv[1]=t[mid].maxv[1]=t[mid].p[1]; t[mid].ch[0]=t[mid].ch[1]=0; t[mid].sumv=t[mid].w; if(mid>l) { t[mid].ch[0]=build(l,mid-1,o^1); pushup(mid,t[mid].ch[0]); } if(r>mid) { t[mid].ch[1]=build(mid+1,r,o^1); pushup(mid,t[mid].ch[1]); } return mid; } ll qmin(int x,ll a,ll b) { ll ans=0; for(int i=0;i<2;++i) { ans+=min(A[i]*1ll*t[x].minv[i], A[i]*1ll*t[x].maxv[i]); } return ans; } ll qmax(int x,ll a,ll b) { ll ans=0; for(int i=0;i<2;++i) { ans+=max(A[i]*1ll*t[x].minv[i], A[i]*1ll*t[x].maxv[i]); } return ans; } ll query(int x,ll a,ll b) { if(qmax(x, a, b) < C) return t[x].sumv; if(qmin(x, a, b) >= C) return 0; ll ans=0; if(1ll*t[x].p[0]*a+1ll*t[x].p[1]*b < C) ans+=t[x].w; if(lson) ans+=query(lson,a,b); if(rson) ans+=query(rson,a,b); return ans; } int main() { // setIO("input"); scanf("%d%d",&n,&Q); for(int i=1;i<=n;++i) scanf("%d%d%lld",&t[i].p[0],&t[i].p[1],&t[i].w); int root=build(1,n,0); while(Q--) { scanf("%lld%lld%lld",&A[0],&A[1],&C); printf("%lld\n",query(root, A[0], A[1])); } return 0; }