巧克力王國裏的巧克力都是由牛奶和可可作成的。ui
可是並非每一塊巧克力都受王國人民的歡迎,由於你們都不喜歡過於甜的巧克力。spa
對於每一塊巧克力,咱們設 x 和 y 爲其牛奶和可可的含量。blog
因爲每一個人對於甜的程度都有本身的評判標準,因此每一個人都有兩個參數 a 和 b ,分別爲他本身爲牛奶和可可定義的權重, 所以牛奶和可可含量分別爲 x 和 y 的巧克力對於他的甜味程度即爲 ax+by。element
而每一個人又有一個甜味限度 c ,全部甜味程度大於等於 c 的巧克力他都沒法接受。get
每塊巧克力都有一個美味值 h 。it
如今咱們想知道對於每一個人,他所能接受的巧克力的美味值之和爲多少。io
輸入格式:class
第一行兩個正整數 n 和 m ,分別表示巧克力個數和詢問個數。
接下來n行,每行三個整數 x , y , h ,含義如題目所示。
再接下來 m 行,每行三個整數 a , b , c,含義如題目所示。stream
輸出格式:
輸出m行,其中第i行表示第i我的所能接受的巧克力的美味值之和。
對於100%的數據,$1<=n,m<=50000,-10^9<=a_i,b_i,x_i,y_i<=10^9$。
巧克力。。。不是凰麼???
莫名的病嬌既視感。。。
若是把那個$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\n",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; }