zoukankan      html  css  js  c++  java
  • 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
    ",query(root, A[0], A[1]));    
        }
        return 0; 
    }
    

      

  • 相关阅读:
    java8学习之Collector复合与注意事项
    动画学习之WIFI图形绘制
    java线程基础巩固---多线程死锁分析,案例介绍
    java8学习之Collector同一性与结合性分析
    java8学习之Collector源码分析与收集器核心
    java8学习之Stream分组与分区详解
    kotlin面向对象之抽象类、继承、多态
    matplotlib-曲线和折线案例
    人口、人口密度分析项目-条形图
    开机自启:bat实现一次性打开win7中的常用软件和文件夹
  • 原文地址:https://www.cnblogs.com/guangheli/p/11058996.html
Copyright © 2011-2022 走看看