题目:
题解:
和上一道题目一样,这道题目的基本思路:抽象成二维—>每次查询从树里找有效解,分区间查询
我们可以把x,y抽象为二维的点,那么每次询问都是ax+by<=c就是这条直线的下方点权数
难点就是如何判断这条直线有没有与某个区间相交,我们已经用KD-tree记录了4个值:管辖区间内的最左值、最右值、最上值、最下值
可以组合为4个极端点:左上、右上、左下、右下
如果这四个极端点都在范围内,那就是全都涵盖啦,我们就一股脑的加进去
如果这四个极端点都不在范围内,那就是没有交点啊,直接跳过
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
struct hh{int l,r,d[2],mn[2],mx[2];LL sum,zz;}t[50005];
int cmpd,root;LL ans,a,b,c;
int cmp(const hh &a,const hh &b)
{
return (a.d[cmpd]<b.d[cmpd] || (a.d[cmpd]==b.d[cmpd] && a.d[!cmpd]<b.d[!cmpd]));
}
void updata(int now)
{
int lc=t[now].l,rc=t[now].r;
t[now].sum=t[now].zz;
if (lc)
{
t[now].mn[0]=min(t[now].mn[0],t[lc].mn[0]);
t[now].mn[1]=min(t[now].mn[1],t[lc].mn[1]);
t[now].mx[0]=max(t[now].mx[0],t[lc].mx[0]);
t[now].mx[1]=max(t[now].mx[1],t[lc].mx[1]);
t[now].sum+=t[lc].sum;
}
if (rc)
{
t[now].mn[0]=min(t[now].mn[0],t[rc].mn[0]);
t[now].mn[1]=min(t[now].mn[1],t[rc].mn[1]);
t[now].mx[0]=max(t[now].mx[0],t[rc].mx[0]);
t[now].mx[1]=max(t[now].mx[1],t[rc].mx[1]);
t[now].sum+=t[rc].sum;
}
}
int build(int l,int r,int D)
{
cmpd=D;
int mid=(l+r)>>1;
nth_element(t+l+1,t+mid+1,t+r+1,cmp);
t[mid].mn[0]=t[mid].mx[0]=t[mid].d[0];
t[mid].mn[1]=t[mid].mx[1]=t[mid].d[1];
t[mid].sum=t[mid].zz;
if (l<mid) t[mid].l=build(l,mid-1,!D);
if (r>mid) t[mid].r=build(mid+1,r,!D);
updata(mid); return mid;
}
bool ok(int now){return ((LL)t[now].d[0]*a+(LL)t[now].d[1]*b<c);}
int check(int now)
{
int d=0;
if ((LL)t[now].mn[0]*a+(LL)t[now].mn[1]*b<c) d++;//左下
if ((LL)t[now].mn[0]*a+(LL)t[now].mx[1]*b<c) d++;//左上
if ((LL)t[now].mx[0]*a+(LL)t[now].mn[1]*b<c) d++;//右下
if ((LL)t[now].mx[0]*a+(LL)t[now].mx[1]*b<c) d++;//右上
return d;
}
void qurry(int now)
{
if (ok(now)) ans+=t[now].zz;
if (t[now].l)
{
int bh=check(t[now].l);
if (bh==4) ans+=t[t[now].l].sum;
else if (bh!=0) qurry(t[now].l);
}
if (t[now].r)
{
int bh=check(t[now].r);
if (bh==4) ans+=t[t[now].r].sum;
else if (bh!=0) qurry(t[now].r);
}
}
int main()
{
int n,m,i;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) scanf("%lld%lld%lld",&t[i].d[0],&t[i].d[1],&t[i].zz);
root=build(1,n,0);
while (m--)
{
scanf("%lld%lld%lld",&a,&b,&c);
ans=0;
qurry(root);
printf("%lld\n",ans);
}
}