bzoj 2850 巧克力王国——KDtree

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2850

改一下估价即可。判断子树能否整个取或者是否整个不能取,时间好像就能行了?

因为有负数,所以判一下四个边界。注意这个区域本身还占了一个点。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=5e4+5;
int n,m,rt,tot,fx;
ll A,B,C;
struct Dt{
    ll x[2],y[2],p[2],h,ph;
}a[N];
bool cmp(Dt u,Dt v){return u.p[fx]<v.p[fx];}
struct KD{
    int c[N][2];Dt s[N];
    void add(int cr,Dt k)
    {
        for(int i=0;i<=1;i++) s[cr].x[i]=s[cr].y[i]=s[cr].p[i]=k.p[i];
        s[cr].h=s[cr].ph=k.h;
    }
    void pshp(int cr)
    {
        int ls=c[cr][0],rs=c[cr][1];
        for(int i=0;i<=1;i++)
        {
            if(ls)  s[cr].x[i]=min(s[cr].x[i],s[ls].x[i]),
                    s[cr].y[i]=max(s[cr].y[i],s[ls].y[i]);
            if(rs)  s[cr].x[i]=min(s[cr].x[i],s[rs].x[i]),
                    s[cr].y[i]=max(s[cr].y[i],s[rs].y[i]);
        }
        s[cr].h=(ls?s[ls].h:0)+(rs?s[rs].h:0)+s[cr].ph;
    }
    void build(int &cr,int l,int r,bool now)
    {
        int mid=l+r>>1;  fx=now;  nth_element(a+l,a+mid,a+r+1,cmp);
        cr=++tot;  add(cr,a[mid]);
        if(l<mid) build(c[cr][0],l,mid-1,!now);
        if(mid<r) build(c[cr][1],mid+1,r,!now);
        pshp(cr);
//        printf("cr=%d(x:%lld~%lld y:%lld~%lld h=%lld)\n",cr,s[cr].x[0],
//            s[cr].y[0],s[cr].x[1],s[cr].y[1],s[cr].h);
    }
    int check(int cr)
    {
        int ret=0;
        ret+=(A*s[cr].x[0]+B*s[cr].x[1]<C);
        ret+=(A*s[cr].x[0]+B*s[cr].y[1]<C);
        ret+=(A*s[cr].y[0]+B*s[cr].x[1]<C);
        ret+=(A*s[cr].y[0]+B*s[cr].y[1]<C);
        return ret;
    }
    ll query(int cr)
    {
        ll ret=(A*s[cr].p[0]+B*s[cr].p[1]<C?s[cr].ph:0);
        int ls=c[cr][0],rs=c[cr][1];
        int dl=(ls?check(ls):0),dr=(rs?check(rs):0);
//        printf("cr=%d(x:%lld~%lld y:%lld~%lld h=%lld) dl=%d dr=%d\n"
//            ,cr,s[cr].x[0],s[cr].y[0],s[cr].x[1],s[cr].y[1],s[cr].h,dl,dr);
        if(dl==4) ret+=s[ls].h;  else if(dl) ret+=query(ls);
        if(dr==4) ret+=s[rs].h;  else if(dr) ret+=query(rs);
        return ret;
    }
}kd;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld%lld",&a[i].p[0],&a[i].p[1],&a[i].h);
    kd.build(rt,1,n,0);
    for(int i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&A,&B,&C);
        printf("%lld\n",kd.query(rt));
    }
    return 0;
}

 

posted on 2018-09-06 18:55  Narh  阅读(156)  评论(0编辑  收藏  举报

导航