题意:n个平面上的带权点,每次给出a,b,h,询问满足ax+by < h的点权和。
1 <= n, m <= 50000,其它10^9
kdtree划分矩形,显然若矩形四个顶点都在半平面内,则整个矩形在半平面内;四个顶点都在半平面外,则整个矩形在半平面外。
注意维护的是权值和,不是size
#include<cstdio>
#include<algorithm>
using std::nth_element;
typedef long long ll;
struct chok
{
int p[2],v;
chok(){}
chok(int x,int y,int z):v(z){p[0]=x,p[1]=y;}
inline int& operator [] (size_t x){return p[x];}
inline const int& operator [] (size_t x) const {return p[x];}
};
inline int check(ll a,ll b,ll c,int x,int y)
{
return a*x+b*y<c;
}
bool cmp;
inline bool fn(const chok &a,const chok &b)
{
return a[cmp]<b[cmp];
}
inline void min(int &a,int b)
{
if(b<a) a=b;
}
inline void max(int &a,int b)
{
if(a<b) a=b;
}
struct node
{
ll sum;
chok p;
int xn,yn,xm,ym;
node *l,*r;
node(const chok &p):sum(p.v),p(p),l(0),r(0),xn(p[0]),yn(p[1]),xm(p[0]),ym(p[1]){}
inline void* operator new(size_t)
{
static unsigned char pool[50000*sizeof(node)];
static node* s=(node*)pool;
static size_t k=-1;
return s+ ++k;
}
ll query(int a,int b,int c)
{
if(!this) return 0;
int tot=check(a,b,c,xn,yn)+check(a,b,c,xn,ym)+check(a,b,c,xm,yn)+check(a,b,c,xm,ym);
if(tot==4) return sum;
if(!tot) return 0;
ll res=0;
if(check(a,b,c,p[0],p[1])) res+=p.v;
return res+l->query(a,b,c)+r->query(a,b,c);
}
inline void up()
{
if(l) min(xn,l->xn),min(yn,l->yn),max(xm,l->xm),max(ym,l->ym),sum+=l->sum;
if(r) min(xn,r->xn),min(yn,r->yn),max(xm,r->xm),max(ym,r->ym),sum+=r->sum;
}
};
struct kdtree
{
node *rt;
node *build(chok* l,chok *r,bool k)
{
if(l==r) return 0;
chok *mid=l+(r-l>>1);
cmp=k;
nth_element(l,mid,r,fn);
node *kre=new node(*mid);
kre->l=build(l,mid,!k);
kre->r=build(mid+1,r,!k);
kre->up();
return kre;
}
kdtree(chok *a,int len):rt(build(a,a+len,0)){}
inline ll query(int a,int b,int c)
{
return rt->query(a,b,c);
}
};
int n,m;
chok choco[50000];
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i)
scanf("%d%d%d",&choco[i].p[0],&choco[i].p[1],&choco[i].v);
kdtree tr(choco,n);
for(int i=0;i<m;++i)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
printf("%lld\n",tr.query(a,b,c));
}
return 0;
}