巧克力王国
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
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。
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 }