题目描述
巧克力王国里的巧克力都是由牛奶和可可做成的。
但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力。
对于每一块巧克力,我们设 x 和 y 为其牛奶和可可的含量。
由于每个人对于甜的程度都有自己的评判标准,所以每个人都有两个参数 a 和 b ,分别为他自己为牛奶和可可定义的权重, 因此牛奶和可可含量分别为 x 和 y 的巧克力对于他的甜味程度即为 ax+by。
而每个人又有一个甜味限度 c ,所有甜味程度大于等于 c 的巧克力他都无法接受。
每块巧克力都有一个美味值 h 。
现在我们想知道对于每个人,他所能接受的巧克力的美味值之和为多少。
输入输出格式
输入格式:
第一行两个正整数 n 和 m ,分别表示巧克力个数和询问个数。
接下来n行,每行三个整数 x , y , h ,含义如题目所示。
再接下来 m 行,每行三个整数 a , b , c,含义如题目所示。
输出格式:
输出m行,其中第i行表示第i个人所能接受的巧克力的美味值之和。
输入输出样例
说明
对于100%的数据,$1<=n,m<=50000,-10^9<=a_i,b_i,x_i,y_i<=10^9$。
题解Here!
巧克力。。。不是凰么???
莫名的病娇既视感。。。
如果把那个$ax+by<c$看成半平面的话,这个成就成了平面上某一区域内所有点的点权和。
这种问题直接$K-D Tree$就好。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 50010 #define MAX (1LL<<60) using namespace std; int n,m,root; bool sort_flag=false; struct Point{ long long x,y,z; friend bool operator <(const Point &p,const Point &q){ if(sort_flag)return p.y<q.y; return p.x<q.x; } }point[MAXN],now; struct Tree{ Point point; long long minx,miny,maxx,maxy,val,sum; int lson,rson; }a[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } void pushup(int rt){ int lson=a[rt].lson,rson=a[rt].rson; a[rt].sum=a[lson].sum+a[rson].sum+a[rt].val; a[rt].maxx=max(a[rt].maxx,max(a[lson].maxx,a[rson].maxx)); a[rt].maxy=max(a[rt].maxy,max(a[lson].maxy,a[rson].maxy)); a[rt].minx=min(a[rt].minx,min(a[lson].minx,a[rson].minx)); a[rt].miny=min(a[rt].miny,min(a[lson].miny,a[rson].miny)); } void buildtree(int l,int r,int &rt,int flag){ int mid=l+r>>1; rt=mid; sort_flag=flag; nth_element(point+l,point+mid,point+r+1); a[rt].point=point[mid]; a[rt].val=point[mid].z; a[rt].maxx=a[rt].minx=point[mid].x; a[rt].maxy=a[rt].miny=point[mid].y; if(l<mid)buildtree(l,mid-1,a[rt].lson,flag^1); if(mid<r)buildtree(mid+1,r,a[rt].rson,flag^1); pushup(rt); } inline bool check(int rt){ return ((a[rt].point.x*now.x+a[rt].point.y*now.y)<now.z); } inline long long max_dis(int rt){ long long x,y; x=max(a[rt].minx*now.x,a[rt].maxx*now.x); y=max(a[rt].miny*now.y,a[rt].maxy*now.y); return x+y; } inline long long min_dis(int rt){ long long x,y; x=min(a[rt].minx*now.x,a[rt].maxx*now.x); y=min(a[rt].miny*now.y,a[rt].maxy*now.y); return x+y; } long long query(int rt){ long long dis=max_dis(rt); if(dis<now.z)return a[rt].sum; dis=min_dis(rt); if(dis>=now.z)return 0; long long ans=0; if(check(rt))ans+=a[rt].val; if(a[rt].lson)ans+=query(a[rt].lson); if(a[rt].rson)ans+=query(a[rt].rson); return ans; } void work(){ while(m--){ now.x=read();now.y=read();now.z=read(); printf("%lld ",query(root)); } } void init(){ n=read();m=read(); a[0].maxx=a[0].maxy=-MAX; a[0].minx=a[0].miny=MAX; for(int i=1;i<=n;i++){point[i].x=read();point[i].y=read();point[i].z=read();} buildtree(1,n,root,0); } int main(){ init(); work(); return 0; }