BZOJ4009 接水果

版权声明:随意转载,愿意的话提一句作者就好了 https://blog.csdn.net/stone41123/article/details/84061111

Link

Difficulty

算法难度6,思维难度7,代码难度7

Description

给你一棵树,给你若干个盘子,每个盘子对应着一条链和一个权值

会掉下来若干个苹果,每个苹果对应着一条链和一个k

盘子可以接苹果当且仅当盘子的路径是苹果的路径的子路径

苹果会选择可以接住它的盘子中的权值第k小的

求每个苹果被哪个盘子接住,输出权值

1 n , m , q 4 1 0 4 1\le n,m,q\le 4*10^4

Solution

首先权值离散化

然后我们来讨论可以接住苹果的盘子满足什么性质

假设苹果的路径为 ( x , y ) (x,y) ,盘子的路径为 ( x , y ) (x',y')

(以下我们记 d f n ( x ) , e d ( x ) dfn(x),ed(x) 分别为 x x d f s dfs 序和子树内最后一个点的 d f s dfs 序)

  1. l c a ( x , y ) x lca(x',y')\ne x' y y'

    那么我们发现 x , y x,y 只能分别位于 x , y x',y' 的子树内

    即: d f n ( x ) d f n ( x ) e d ( x ) , d f n ( y ) d f n ( y ) e d ( y ) dfn(x')\le dfn(x)\le ed(x'),dfn(y')\le dfn(y)\le ed(y')

    或: d f n ( x ) d f n ( y ) e d ( x ) , d f n ( y ) d f n ( x ) e d ( y ) dfn(x')\le dfn(y)\le ed(x'),dfn(y')\le dfn(x)\le ed(y')

    这时你就会发现盘子的限制条件可以分成两个矩形

  2. l c a ( x , y ) = x lca(x',y')=x' (另一种也一样)

    那我们记 ( x , y ) (x',y') 上最靠近 x x' 的那个点为 z z 的话(也就是深度第二小的点)

    那么我们发现 x , y x,y 只能一个位于 y y' 的子树内,另一个在 z z 的子树之外

    即: d f n ( y ) d f n ( x ) e d ( y ) , 1 d f n ( y ) < d f n ( z ) dfn(y')\le dfn(x) \le ed(y'),1\le dfn(y)<dfn(z) e d ( z ) < d f n ( y ) n ed(z)<dfn(y) \le n

    或: d f n ( y ) d f n ( y ) e d ( y ) , 1 d f n ( x ) < d f n ( z ) dfn(y')\le dfn(y) \le ed(y'),1\le dfn(x)<dfn(z) e d ( z ) < d f n ( x ) n ed(z)<dfn(x) \le n

    这时你会发现这东西和上面的差不多,只不过这个是四个矩形而已

这时问题就转换成了给定一堆矩形,还有一堆点,矩形带权,对于每个点求包含它的矩形中第k小的权值

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<vector>
#define LL long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=' ';
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return f==1?x:-x;
}
const int N=1e5+5;
int n,m,q,tot,H,Hash[N];
int head[N],to[N],Next[N];
inline void addedge(int x,int y){
    to[++tot]=y;
    Next[tot]=head[x];
    head[x]=tot;
}
int dfn[N],dfn_clock,ed[N],dep[N],st[16][N];
inline void dfs(int x,int fa){
    dfn[x]=++dfn_clock;
    dep[x]=dep[fa]+1;
    st[0][x]=fa;
    for(int i=1;i<=15;++i)st[i][x]=st[i-1][st[i-1][x]];
    for(int i=head[x];i;i=Next[i]){
        int u=to[i];
        if(u==fa)continue;
        dfs(u,x);
    }
    ed[x]=dfn_clock;
}
inline int getlca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=15;i>=0;--i)
        if(dep[st[i][x]]>=dep[y])
            x=st[i][x];
    if(x==y)return x;
    for(int i=15;i>=0;--i)
        if(st[i][x]!=st[i][y])
            x=st[i][x],y=st[i][y];
    return st[0][x];
}
inline int jump(int x,int y){
    for(int i=15;i>=0;--i)
        if(dep[st[i][x]]>dep[y])
            x=st[i][x];
    return x;
}
struct data{
    int x,y1,y2,val,id,type;
    data(){}
    data(int _x,int _y1,int _y2,int _val,int _id,int _type):
        x(_x),y1(_y1),y2(_y2),val(_val),id(_id),type(_type){}
    inline bool operator < (const data& b) const {
        if(x==b.x)return type<b.type;
        else return x<b.x;
    }
};
vector<data> t;
int a[N];
inline void modify(int x,int v){
    while(x<=n){
        a[x]+=v;
        x+=x&-x;
    }
}
inline int query(int x){
    int ans=0;
    while(x){
        ans+=a[x];
        x-=x&-x;
    }
    return ans;
}
int ans[N];
inline void solve(vector<data> &t,int l,int r){
    if(l==r){
        for(vector<data>::iterator it=t.begin();it!=t.end();++it){
            if((*it).type==2)
                ans[(*it).id]=Hash[l];
        }
        return;
    }
    int mid=(l+r)>>1;
    vector<data> ls,rs;
    for(vector<data>::iterator it=t.begin();it!=t.end();++it){
        data d=*it;
        if(d.type==2){
            int num=query(d.y1);
            if(d.val<=num)ls.push_back(d);
            else{
                d.val-=num;
                rs.push_back(d);
            }
        }
        else{
            if(d.val<=mid)ls.push_back(d);
            else rs.push_back(d);
            if(d.val>mid)continue;
            modify(d.y1,d.id);
            modify(d.y2+1,-d.id);
        }
    }
    solve(ls,l,mid);
    solve(rs,mid+1,r);
}
int main(){
    n=read();m=read();q=read();
    for(int i=1;i<n;++i){
        int x=read(),y=read();
        addedge(x,y);addedge(y,x);
    }
    dfs(1,0);
    for(int i=1;i<=m;++i){
        int x=read(),y=read(),c=read();
        int lca=getlca(x,y);
        Hash[++H]=c;
        if(lca!=x && lca!=y){
            t.push_back(data(dfn[x],dfn[y],ed[y],c,1,1));
            t.push_back(data(ed[x],dfn[y],ed[y],c,-1,3));
            t.push_back(data(dfn[y],dfn[x],ed[x],c,1,1));
            t.push_back(data(ed[y],dfn[x],ed[x],c,-1,3));
        }
        else{
            if(lca==y)swap(x,y);
            int z=jump(y,x);
            t.push_back(data(1,dfn[y],ed[y],c,1,1));
            t.push_back(data(dfn[z]-1,dfn[y],ed[y],c,-1,3));
            t.push_back(data(ed[z]+1,dfn[y],ed[y],c,1,1));
            t.push_back(data(n,dfn[y],ed[y],c,-1,3));
            t.push_back(data(dfn[y],1,dfn[z]-1,c,1,1));
            t.push_back(data(dfn[y],ed[z]+1,n,c,1,1));
            t.push_back(data(ed[y],1,dfn[z]-1,c,-1,3));
            t.push_back(data(ed[y],ed[z]+1,n,c,-1,3));
        }
    }
    for(int i=1;i<=q;++i){
        int x=read(),y=read(),c=read();
        t.push_back(data(dfn[x],dfn[y],-1,c,i,2));
    }
    sort(Hash+1,Hash+H+1);
    H=unique(Hash+1,Hash+H+1)-Hash-1;
    for(vector<data>::iterator it=t.begin();it!=t.end();++it){
        if((*it).type!=2)
            (*it).val=lower_bound(Hash+1,Hash+H+1,(*it).val)-Hash;
    }
    sort(t.begin(),t.end());
    solve(t,1,H);
    for(int i=1;i<=q;++i)printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/stone41123/article/details/84061111
今日推荐