bzoj2850巧克力王国

巧克力王国

Time Limit: 60 Sec  Memory Limit: 512 MB
Submit: 861  Solved: 325
[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。

 
题解:
  这是一个二维平面问题,应该想到扫描线或者kdtree,
  但是发现对于扫描线,无法解决问题,因为限制是ax+by,所以对于每个询问是不一样的。
  所以是不行的,二kdtree是可以解决的,
  对于暴力只能够一个一个处理,如何一起处理是解决问题的关键,
  所以需要kdtree。
  时间复杂度,对于建树是T(n)=f(n)+aT(n/b)=O(n)+2T(n/2)
  所以得出复杂度是O(n log n)的
  然后对于询问是n^(1-1/k)是√n的,所以渐进复杂度是O(n√n)的。
 1 #include<cstring>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdio>
 6 
 7 #define ll long long
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 ll A,B,C,ans;
17 int F,n,m,rt;
18 struct Node
19 {
20     int d[2],mx[2],mn[2],v,l,r;
21     ll sum;
22     int& operator[](int x)
23     {
24         return d[x];
25     }
26     friend bool operator<(Node x,Node y)
27     {
28         return x[F]<y[F];
29     }
30 }p[50007];
31 bool check(int x,int y)
32 {
33     return A*x+B*y<C;
34 }
35 int cal(Node x)
36 {
37     int tmp=0;
38     tmp+=check(x.mn[0],x.mn[1]);
39     tmp+=check(x.mx[0],x.mn[1]);
40     tmp+=check(x.mn[0],x.mx[1]);
41     tmp+=check(x.mx[0],x.mx[1]);
42     return tmp;
43 }
44 struct kd
45 {
46     Node t[50007];
47     void update(int p)
48     {
49         int l=t[p].l,r=t[p].r;
50         for (int i=0;i<2;i++)
51         {
52             t[p].mn[i]=t[p].mx[i]=t[p][i];
53             if (l) t[p].mn[i]=min(t[p].mn[i],t[l].mn[i]);
54             if (r) t[p].mn[i]=min(t[p].mn[i],t[r].mn[i]);
55             if (l) t[p].mx[i]=max(t[p].mx[i],t[l].mx[i]);
56             if (r) t[p].mx[i]=max(t[p].mx[i],t[r].mx[i]);
57         }
58         t[p].sum=t[p].v+t[l].sum+t[r].sum;
59     }
60     int build(int l,int r,int now)
61     {
62         F=now;
63         int mid=(l+r)>>1;
64         nth_element(p+l,p+mid,p+r+1);
65         t[mid]=p[mid];
66         if (l<mid) t[mid].l=build(l,mid-1,now^1);
67         if (r>mid) t[mid].r=build(mid+1,r,now^1);
68         update(mid);
69         return mid;
70     }
71     void query(int p)
72     {
73         int l=t[p].l,r=t[p].r;
74         if (check(t[p][0],t[p][1]))ans+=t[p].v;
75         int tl=0,tr=0;
76         if (l) tl=cal(t[l]);
77         if (r) tr=cal(t[r]);
78         if (tl==4) ans+=t[l].sum;
79         else if (tl) query(l);
80         if (tr==4) ans+=t[r].sum;
81         else if (tr) query(r); 
82     }
83 }kd;
84 int main()
85 {
86     n=read(),m=read();
87     for (int i=1;i<=n;i++)
88         p[i][0]=read(),p[i][1]=read(),p[i].v=read();
89     rt=kd.build(1,n,0);
90     while(m--)
91     {
92         A=read(),B=read(),C=read();
93         ans=0;
94         kd.query(rt);
95         printf("%lld
",ans);
96     }    
97 }
 
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8175714.html