【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
 
原文地址:https://www.cnblogs.com/BearChild/p/6424290.html