KD-tree

bzoj4520k远点对(堆乱搞2*k个值)
剪枝:判断点到矩形距离与堆顶的关系。

    //任意两点对
    ll gdis(node a,node now){
        ll res=0;
        res+=max(sqr(a.mn[0]-now.d[0]),sqr(a.mx[0]-now.d[0]));
        res+=max(sqr(a.mn[1]-now.d[1]),sqr(a.mx[1]-now.d[1]));
        return res;
    }

bzoj2850√Ax+By<C
剪枝:判断一个矩形内是否一定全都合法(直接加sum)。

bzoj4605

bzoj2716&&2648插入点时要每插入n个点重构一次
剪枝:判断点到矩形距离与答案的关系

这里写图片描述

    //查询一个点到另一个点的最短曼哈顿距离
    int gdis(node a,node now){
        //询问的当前点到搞到的kd-tree的矩形的距离
        int res=0;
        for (int i=0;i<=1;i++){
            res+=max(0,now.d[i]-a.mx[i]);
            res+=max(0,a.mn[i]-now.d[i]);
        }
        return res;
    }

bzoj3053k[1~5]维,输出m近点对。
剪枝:判断点到矩形距离与堆顶的关系。

    给定一个点,弄另一个点。
    ll gdis(node a,pd now){
        ll res=0;
        for (int i=0;i<m;i++){
            if (now.c[i]<a.mn[i])
                res+=sqr(now.c[i]-a.mn[i]);
            if (now.c[i]>a.mx[i])
                res+=sqr(now.c[i]-a.mx[i]);
        }
        return res;
    }

bzoj4066&&2683

bzoj2626 二维第k远点

bzoj3489 三维,第一维是这个数上一次出现位置,第二维是当前位置,第三维是下一次出现位置

bzoj1941二维,搞出每个点的最远距离和最近距离

bzoj4130
bzoj3616
bzoj4154
题意:
 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过len的a的子节点染成c,或询问点a的颜色
 
分析:
 将每个树上节点变为平面上的点(dfs)
对于每个修改,就将平面x[dfsdfs]y[dep[x]dep[x]+len]。区间包含的就打tag,tag要下传后清空
对于每个询问,就看当前区间是否包含该节点且有整个区间的tag,不然就暴搞进去。

bzoj4170
bzoj4538
bzoj1790
bzoj4553

//bzoj2850
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
typedef long long ll;
const int N=50010;
int n,m,F,root;
ll x,y,z,ans;

int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

struct node{
    int d[2],mn[2],mx[2],v,l,r;
    ll sum;
    friend bool operator < (node a,node b){
        return a.d[F]<b.d[F];
    }
}p[N];

int check(int a,int b){
    return x*a+y*b<z;
}

int calc(node a){
    int res=0;
    res+=check(a.mn[0],a.mn[1]);
    res+=check(a.mn[0],a.mx[1]);
    res+=check(a.mx[0],a.mn[1]);
    res+=check(a.mx[0],a.mx[1]);
    return res;
}

struct kd_tree{
    node t[N];
    void pushup(int rt){
        int l=t[rt].l,r=t[rt].r;
        for (int i=0;i<=1;i++){
            t[rt].mx[i]=t[rt].mn[i]=t[rt].d[i];
            if (l) t[rt].mn[i]=min(t[rt].mn[i],t[l].mn[i]);
            if (r) t[rt].mx[i]=max(t[rt].mx[i],t[r].mx[i]);
            if (l) t[rt].mx[i]=max(t[rt].mx[i],t[l].mx[i]);
            if (r) t[rt].mn[i]=min(t[rt].mn[i],t[r].mn[i]);
        }
        t[rt].sum=t[rt].v+t[l].sum+t[r].sum;
    }
    int build(int l,int r,int now){
    /*
        用方差决定是切割哪一维
        double _x=0,_y=0; 
        F(i,l,r) 
        _x+=t[i].d[0],
        _y+=t[i].d[1]; 

        _x/=r-l+1,_y/=r-l+1;
        double x_=0,y_=0; 
        x_+=sqr(t[i].d[0]-_x),
        y_+=sqr(t[i].d[1]-_y); 
        F=y_>x_;
    */
        F=now;int mid=(l+r)>>1;
        nth_element(p+l,p+mid,p+r+1);
        t[mid]=p[mid];
        if (l<mid) t[mid].l=build(l,mid-1,now^1);
        if (r>mid) t[mid].r=build(mid+1,r,now^1);
        pushup(mid);return mid;
    }
    void query(int rt){
        int l=t[rt].l,r=t[rt].r;
        if (check(t[rt].d[0],t[rt].d[1]))
            ans+=t[rt].v;
        if (l){
            int tl=calc(t[l]);
            if (tl==4)
                ans+=t[l].sum; else
            if (tl)
                query(l);
        }
        if (r){
            int tr=calc(t[r]);
            if (tr==4)
                ans+=t[r].sum; else
            if (tr)
                query(r);
        }
    }
}tree;

int main(){
    freopen("d.in","r",stdin);
    n=read();m=read();
    for (int i=1;i<=n;i++){
        p[i].d[0]=read();
        p[i].d[1]=read();
        p[i].v=read();
    }
    root=tree.build(1,n,0);
    while (m--){
        x=read();
        y=read();
        z=read();
        ans=0;
        tree.query(root);
        printf("%lld\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值