【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
",ans);
      }
    return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/4587118.html