zoukankan      html  css  js  c++  java
  • 【BZOJ2850】巧克力王国 [KD-tree]

    巧克力王国

    Time Limit: 60 Sec  Memory Limit: 512 MB
    [Submit][Status][Discuss]

    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个人所能接受的巧克力的美味值之和。

    Sample Input

      3 3
      1 2 5
      3 1 4
      2 2 1
      2 1 6
      1 3 5
      1 3 7

    Sample Output

      5
      0
      4

    HINT

      1 <= n, m <= 50000,1 <= 10^9,-10^9 <= a, b, x, y <= 10^9。

    Main idea

      每个点(x,y)以及价值,对于每个询问给定A,B,C。对于一个点,若A*x+B*y<C则可以获得该点的价值,问每个点可以得到的价值总和。

     

    Solution

      看到这种在平面上的题,我们显然想到了KD-tree

      因为可以离线,所以我们可以直接在建树的时候运用nth_element函数让它平衡。

      对于每个点记录子树的最大最小的x与y以及总价值,然后KD-tree建树建完之后,查询的时候,如果所有情况都<C,我们就可以直接取走这个子树里面所有的值,如果存在可能的可能性就往下走。

      PS:nth_element: 将一段序列从中间分开,给定的一个值放在中间(我们取中间的值即可),剩下两边排放,效率O(n) 。

    Code

      1 #include<iostream>    
      2 #include<string>    
      3 #include<algorithm>    
      4 #include<cstdio>    
      5 #include<cstring>    
      6 #include<cstdlib>    
      7 #include<cmath>    
      8 #include<map>  
      9 using namespace std;  
     10 
     11 typedef long long s64;
     12 
     13 const int ONE=1000001;
     14 const int INF=2147483640;
     15 
     16 int n,m;
     17 int x,y,A,B;
     18 s64 C,h;
     19 int root;
     20 s64 Ans;
     21 int Ran;
     22 
     23 struct power
     24 {
     25         int x,y,l,r;
     26         int maxx,maxy; 
     27         int minx,miny;
     28         s64 val,sum;
     29 }a[ONE];
     30 
     31 int get()
     32 {    
     33         int res=1,Q=1;char c;    
     34         while( (c=getchar())<48 || c>57 ) 
     35         if(c=='-')Q=-1; 
     36         res=c-48;     
     37         while( (c=getchar())>=48 && c<=57 )    
     38         res=res*10+c-48;    
     39         return res*Q;    
     40 }
     41 
     42 namespace KD
     43 {
     44         void Update(int i)
     45         {
     46             a[i].sum=a[i].val;
     47             if(a[i].l)
     48             {
     49                 a[i].sum+=a[a[i].l].sum;
     50                 a[i].minx=min(a[i].minx,a[a[i].l].minx);    a[i].miny=min(a[i].miny,a[a[i].l].miny);
     51                 a[i].maxx=max(a[i].maxx,a[a[i].l].maxx);    a[i].maxy=max(a[i].maxy,a[a[i].l].maxy); 
     52             }
     53             if(a[i].r)
     54             {
     55                 a[i].sum+=a[a[i].r].sum;
     56                 a[i].minx=min(a[i].minx,a[a[i].r].minx);    a[i].miny=min(a[i].miny,a[a[i].r].miny);
     57                 a[i].maxx=max(a[i].maxx,a[a[i].r].maxx);    a[i].maxy=max(a[i].maxy,a[a[i].r].maxy);
     58             }
     59         }
     60         
     61         int cmp(const power &a,const power &b)
     62         {
     63             if(Ran) return a.x<b.x; return a.y<b.y;
     64         }
     65         
     66         int Build(int l,int r,int T)
     67         {
     68             int mid=(l+r)/2;
     69             Ran=T;
     70             nth_element(a+l,a+mid,a+r+1,cmp);
     71             if(l<mid) a[mid].l = Build(l,mid-1,T^1);
     72             if(mid<r) a[mid].r = Build(mid+1,r,T^1);
     73             Update(mid);
     74             return mid;
     75         }
     76 }
     77 
     78 int PD(int x,int y)
     79 {
     80         return (s64)A*x+(s64)B*y < C ;
     81 }
     82 
     83 int Check(int i)
     84 {
     85         int res=0;
     86         res+= PD(a[i].minx,a[i].miny);
     87         res+= PD(a[i].minx,a[i].maxy);
     88         res+= PD(a[i].maxx,a[i].miny);
     89         res+= PD(a[i].maxx,a[i].maxy);
     90         return res;
     91 }
     92 
     93 void Query(int i)
     94 {
     95         if(PD(a[i].x,a[i].y)) Ans+=a[i].val;
     96         if(a[i].l)
     97         {
     98             int Record=Check(a[i].l);
     99             if(Record==4) Ans+=a[a[i].l].sum;
    100             else if(Record) Query(a[i].l);
    101         }
    102         if(a[i].r)
    103         {
    104             int Record=Check(a[i].r);
    105             if(Record==4) Ans+=a[a[i].r].sum;
    106             else if(Record) Query(a[i].r);
    107         }
    108 }
    109 
    110 
    111 int main() 
    112 {
    113         n=get();    m=get();
    114         for(int i=1;i<=n;i++) a[i].minx=a[i].miny=INF;
    115         for(int i=1;i<=n;i++)
    116         {
    117             x=get();    y=get();    scanf("%lld",&h);
    118             a[i].val=h;
    119             a[i].x=a[i].minx=a[i].maxx=x;
    120             a[i].y=a[i].miny=a[i].maxy=y;
    121         }
    122         root=KD::Build(1,n,1);
    123         
    124         while(m--)
    125         {
    126             A=get();    B=get();    scanf("%lld",&C);
    127             Ans=0;
    128             Query(root);
    129             printf("%lld
    ",Ans);
    130         }
    131         
    132 }
    View Code
     
  • 相关阅读:
    java 基础学习 关键字、标识符、常量、进制、有符号表示法、变量、数据类型小节
    java 基础学习 异常的处理和自定义 学习总结
    正则表达式应用--实例应用
    ArrayList:去除集合中字符串的重复值 LinkedList:去除集合中自定义对象的重复值
    java IO流中文件,图像,视频,拷贝总结
    递归算法学习心得与体会
    如何打印身份证的正反面
    添加div间距
    Junit:NoSuchMethodError runLeaf runChild
    Ajax:async
  • 原文地址:https://www.cnblogs.com/BearChild/p/6424290.html
Copyright © 2011-2022 走看看