BZOJ4009: [HNOI2015]接水果 kdtree

网上一堆题解这里不再赘述
奈何我连扫描线都写不动只好上kdtree了

#include<cstdio>
#include<cmath>
#include<algorithm>
#define gm 40001
int n,p,q;
int cmp;
struct pnt
{
    int p[2];
    pnt():p(){}
    pnt(int x,int y){p[0]=x,p[1]=y;}
    int& operator[] (size_t x) {return p[x];}
    const int& operator[] (size_t x) const {return p[x];}
    bool operator< (const pnt &b) const{return p[cmp]<b[cmp];}
};
inline void min(int &a,int b){b<a?a=b:0;}
inline void max(int &a,int b){a<b?a=b:0;}
inline void min(pnt &a,const pnt &b){min(a[0],b[0]),min(a[1],b[1]);}
inline void max(pnt &a,const pnt &b){max(a[0],b[0]),max(a[1],b[1]);}
struct pan
{
    pnt ap,bp;
    int val;
    operator int() const {return val;}
    bool inner(const pnt &mn,const pnt &mx) const
    {
        return ap[0]<=mn[0]&&ap[1]<=mn[1]&&bp[0]>=mx[0]&&bp[1]>=mx[1];
    }
    bool outer(const pnt &mn,const pnt &mx) const
    {
        return ap[0]>mx[0]||ap[1]>mx[1]||bp[0]<mn[0]||bp[1]<mn[1];
    }
}pst[gm<<1];
int tot=0;
struct node
{
    node *l,*r;
    pnt p,mn,mx;
    int cnt,kis,mark;
    int *ptr;
    node(const pnt &p,int cnt,int *ptr):l(),r(),p(p),mn(p),mx(p),cnt(cnt),kis(),mark(),ptr(ptr){}
    void up()
    {
        kis=cnt;
        if(l&&l->kis>0&&(kis<=0||l->kis<kis)) kis=l->kis;
        if(r&&r->kis>0&&(kis<=0||r->kis<kis)) kis=r->kis;
    }
    void set(int x)
    {
        cnt-=x; kis-=x;
        mark+=x;
    }
    void down()
    {
        if(mark)
        {
            if(l) l->set(mark);
            if(r) r->set(mark);
            mark=0;
        }
    }
    void cotr()
    {
        if(l) min(mn,l->mn),max(mx,l->mx);
        if(r) min(mn,r->mn),max(mx,r->mx);
        up();
    }
    void force(const pan &kre)
    {
        if(kis>0) return;
        if(!cnt) *ptr=kre.val;
        down();
        if(l) l->force(kre);
        if(r) r->force(kre);
        up();
    }
    void check(const pan &kre)
    {
        if(kis<=0||kre.outer(mn,mx)) return;
        if(kre.inner(mn,mx))
        {
            set(1); force(kre);
            return;
        }
        down();
        if(l) l->check(kre);
        if(r) r->check(kre);
        if(kre.inner(p,p)&&!(--cnt)) *ptr=kre.val;
        up();
    }
}*rt;
struct fruit
{
    pnt p;
    int cnt;
    int *ptr;
    bool operator< (const fruit &b) const {return p<b.p;}
}g[gm];
node *build(int l=1,int r=q,int dir=0)
{
    if(r<l) return 0;
    cmp=dir; int mid=(l+r)>>1;
    std::nth_element(g+l,g+mid,g+r+1);
    node *res=new node(g[mid].p,g[mid].cnt,g[mid].ptr);
    res->l=build(l,mid-1,dir^1);
    res->r=build(mid+1,r,dir^1);
    res->cotr();
    return res;
}
struct e
{
    int t;
    e *n;
    e(int t,e *n):t(t),n(n){}
}*f[gm];
int fa[gm][16],dfn[gm],sz[gm],dep[gm],ct;
void dfs(int x)
{
    dfn[x]=++ct; sz[x]=1;
    for(e *i=f[x];i;i=i->n)
    {
        if(i->t==*fa[x]) continue;
        *fa[i->t]=x;
        dep[i->t]=dep[x]+1;
        dfs(i->t);
        sz[x]+=sz[i->t];
    }
}
inline int jump(int x,int k)
{
    int cnt=0;
    while(k)
    {
        if(k&1) x=fa[x][cnt];
        ++cnt;
        k>>=1;
    }
    return x;
}
#define swap(a,b) ((a)^=(b)^=(a)^=(b))
int ans[gm];
int main()
{
    scanf("%d%d%d",&n,&p,&q);
    for(int i=1;i<n;++i)
    {
        int u,v; scanf("%d%d",&u,&v);
        f[u]=new e(v,f[u]); f[v]=new e(u,f[v]);
    }
    dfs(1);
    for(int i=1,j=log2(n);i<=j;++i)
    for(int k=1;k<=n;++k)
    fa[k][i]=fa[fa[k][i-1]][i-1];
    for(int i=1;i<=p;++i)
    {
        int a,b,c; scanf("%d%d%d",&a,&b,&c);
        if(dep[a]>dep[b]) swap(a,b);
        int x1,x2,y1,y2;
        if(jump(b,dep[b]-dep[a])!=a)
        {
            x1=dfn[a],x2=dfn[a]+sz[a]-1,y1=dfn[b],y2=dfn[b]+sz[b]-1;
            if(y1<x1) swap(x1,y1),swap(x2,y2);
            pst[++tot]=(pan){pnt(x1,y1),pnt(x2,y2),c};
        }
        else
        {
            a=jump(b,dep[b]-dep[a]-1);
            x1=1,x2=dfn[a]-1,y1=dfn[b],y2=dfn[b]+sz[b]-1;
            pst[++tot]=(pan){pnt(x1,y1),pnt(x2,y2),c};
            x1=dfn[b],x2=dfn[b]+sz[b]-1,y1=dfn[a]+sz[a],y2=n;
            pst[++tot]=(pan){pnt(x1,y1),pnt(x2,y2),c};
        }
    }
    std::sort(pst+1,pst+tot+1);
    for(int i=1;i<=q;++i)
    {
        int u,v,k; scanf("%d%d%d",&u,&v,&k);
        u=dfn[u],v=dfn[v];
        if(u>v) swap(u,v);
        g[i]=(fruit){pnt(u,v),k,ans+i};
    }
    rt=build();
    for(int i=1;i<=tot;++i)
    {
        rt->check(pst[i]);
    }
    for(int i=1;i<=q;++i) printf("%d\n",ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值