巧克力王国
Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 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
1 2 5
3 1 4
2 2 1
2 1 6
1 3 5
1 3 7
Sample Output
5
0
4
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 }