【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 2147483647 #define KD 2//ά¶ÈÊý int qp[KD]; ll lim; int n,root,m; bool dn; struct Node { int minn[KD],maxx[KD],p[KD],w; int ch[2]; ll sumv; void Init() { for(int i=0;i<KD;++i) minn[i]=maxx[i]=p[i]; sumv=(ll)w; } }T[N]; void Update(int rt) { for(int i=0;i<2;++i) if(T[rt].ch[i]) { T[rt].sumv+=T[T[rt].ch[i]].sumv; for(int j=0;j<KD;++j) { T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]); T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]); } } } bool operator < (const Node &a,const Node &b){return a.p[dn]<b.p[dn];} int Buildtree(int l=1,int r=n,bool d=0) { dn=d; int m=(l+r>>1); nth_element(T+l,T+m,T+r+1); T[m].Init(); if(l!=m) T[m].ch[0]=Buildtree(l,m-1,d^1); if(m!=r) T[m].ch[1]=Buildtree(m+1,r,d^1); Update(m); return m; } ll ans; void Query0(int rt=root)//a>0,b>0 { if((ll)T[rt].p[0] * (ll)qp[0] + (ll)T[rt].p[1] * (ll)qp[1] < lim) ans+=(ll)T[rt].w; for(int i=0;i<2;++i) if(T[rt].ch[i] && (ll)T[T[rt].ch[i]].minn[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].minn[1] * (ll)qp[1] < lim) { if((ll)T[T[rt].ch[i]].maxx[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].maxx[1] * (ll)qp[1] < lim) ans+=T[T[rt].ch[i]].sumv; else Query0(T[rt].ch[i]); } } void Query1(int rt=root)//a>0,b<0 { if((ll)T[rt].p[0] * (ll)qp[0] + (ll)T[rt].p[1] * (ll)qp[1] < lim) ans+=(ll)T[rt].w; for(int i=0;i<2;++i) if(T[rt].ch[i] && (ll)T[T[rt].ch[i]].minn[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].maxx[1] * (ll)qp[1] < lim) { if((ll)T[T[rt].ch[i]].maxx[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].minn[1] * (ll)qp[1] < lim) ans+=T[T[rt].ch[i]].sumv; else Query1(T[rt].ch[i]); } } void Query2(int rt=root)//a<0,b>0 { if((ll)T[rt].p[0] * (ll)qp[0] + (ll)T[rt].p[1] * (ll)qp[1] < lim) ans+=(ll)T[rt].w; for(int i=0;i<2;++i) if(T[rt].ch[i] && (ll)T[T[rt].ch[i]].maxx[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].minn[1] * (ll)qp[1] < lim) { if((ll)T[T[rt].ch[i]].minn[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].maxx[1] * (ll)qp[1] < lim) ans+=T[T[rt].ch[i]].sumv; else Query2(T[rt].ch[i]); } } void Query3(int rt=root)//a<0,b<0 { if((ll)T[rt].p[0] * (ll)qp[0] + (ll)T[rt].p[1] * (ll)qp[1] < lim) ans+=(ll)T[rt].w; for(int i=0;i<2;++i) if(T[rt].ch[i] && (ll)T[T[rt].ch[i]].maxx[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].maxx[1] * (ll)qp[1] < lim) { if((ll)T[T[rt].ch[i]].minn[0] * (ll)qp[0] + (ll)T[T[rt].ch[i]].minn[1] * (ll)qp[1] < lim) ans+=T[T[rt].ch[i]].sumv; else Query3(T[rt].ch[i]); } } int main() { // freopen("bzoj2850.in","r",stdin); // freopen("bzoj2716.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d%d%d",&T[i].p[0],&T[i].p[1],&T[i].w); Buildtree(); root=(1+n>>1); for(int i=1;i<=m;++i) { ans=0; scanf("%d%d%lld",&qp[0],&qp[1],&lim); if(qp[0]>=0 && qp[1]>=0) Query0(); else if(qp[0]>=0 && qp[1]<0) Query1(); else if(qp[0]<0 && qp[1]>=0) Query2(); else Query3(); printf("%lld\n",ans); } return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/