作为一个骗分神器,kdtree可以解决许多计算几何或者二维数点(代替二维数据结构)的问题
模板题:每个点(x,y,z)坐标(x,y),权值(z)
每个询问A,B,C,求满足
Ax+By<C
的权值和
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 501000
#define ll long long
#define INF 214748347
using namespace std;
ll n,m,tot=1,A,B,C,ans;
struct pt{
ll x,y,z;
}a[N];
struct kdt{
ll x,y,z,x1,y1,x2,y2,l,r,v;
}t[N];
bool cntx(pt a,pt b){return a.x<b.x;}
bool cnty(pt a,pt b){return a.y<b.y;}
void update(int v)
{
t[v].x1=min(min(t[t[v].l].x1,t[t[v].r].x1),t[v].x);
t[v].y1=min(min(t[t[v].l].y1,t[t[v].r].y1),t[v].y);
t[v].x2=max(max(t[t[v].l].x2,t[t[v].r].x2),t[v].x);
t[v].y2=max(max(t[t[v].l].y2,t[t[v].r].y2),t[v].y);
t[v].v=t[v].v+t[t[v].l].v+t[t[v].r].v;
}
void build(int v,int l,int r,int tag)
{
int mid=(l+r)/2;
if(tag==0) nth_element(a+l,a+mid,a+r+1,cntx);
else nth_element(a+l,a+mid,a+r+1,cnty);
t[v].x=t[v].x1=t[v].x2=a[mid].x;t[v].y=t[v].y1=t[v].y2=a[mid].y;
t[v].v=t[v].z=a[mid].z;
if(l<mid) t[v].l=++tot,build(t[v].l,l,mid-1,tag^1);
if(mid<r) t[v].r=++tot,build(t[v].r,mid+1,r,tag^1);
update(v);
}
int get(ll x,ll y){return A*x+B*y<C?1:0;}
int sch(int v){return get(t[v].x1,t[v].y1)+get(t[v].x1,t[v].y2)+get(t[v].x2,t[v].y1)+get(t[v].x2,t[v].y2);}
void query(int v)
{
if(get(t[v].x,t[v].y)) ans+=t[v].z;
int jy;
if(t[v].l)
{
jy=sch(t[v].l);
if(jy==4) ans+=t[t[v].l].v;
else if(jy) query(t[v].l);
}
if(t[v].r)
{
jy=sch(t[v].r);
if(jy==4) ans+=t[t[v].r].v;
else if(jy) query(t[v].r);
}
}
int main()
{
scanf("%lld%lld",&n,&m);
fo(i,1,n) scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].z);
t[0].x1=t[0].y1=INF,t[0].x2=t[0].y2=-INF,t[0].v=0;
build(1,1,n,0);
while(m--)
{
scanf("%lld%lld%lld",&A,&B,&C);
ans=0;query(1);
printf("%lld\n",ans);
}
}