• 2019南昌网络赛 J Distance on the tree 主席树+lca


    题意

    给一颗树,每条边有边权,每次询问(u)(v)的路径中有多少边的边权小于等于(k​)

    分析

    在树的每个点上建(1​)(i​)的权值线段树,查询的时候同时跑(u,v,lca(u,v)​)三个版本的线段树,查询(1​)(k​)的树上差分和(val[u]+val[v]-2*val[lca]​)

    Code

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define pb push_back
    using namespace std;
    typedef long long ll;
    const int inf=1e9;
    const int maxn=2e5+10;
    int n,m,q;
    int a[maxn],b[maxn];
    typedef pair<int,int> pii;
    vector<pii>g[maxn];
    int top[maxn],sz[maxn],f[maxn],son[maxn],d[maxn];
    int val[maxn*30],ls[maxn*30],rs[maxn*30],rt[maxn],tot;
    int qu[maxn],qv[maxn],qk[maxn];
    void bd(int l,int r,int &p){
        val[++tot]=val[p],ls[tot]=ls[p],rs[tot]=rs[p],p=tot;
        if(l==r) return;int mid=l+r>>1;
        bd(l,mid,ls[p]);bd(mid+1,r,rs[p]);
    }
    void up(int k,int l,int r,int &p){
        val[++tot]=val[p]+1,ls[tot]=ls[p],rs[tot]=rs[p],p=tot;
        if(l==r) return;int mid=l+r>>1;
        if(k<=mid) up(k,l,mid,ls[p]);
        else up(k,mid+1,r,rs[p]);
    }
    int qy(int k,int l,int r,int a,int b,int c){
        int ret=0;
        if(l>=1&&r<=k) return val[a]+val[b]-2*val[c];
        int mid=l+r>>1;
        if(1<=mid) ret+=qy(k,l,mid,ls[a],ls[b],ls[c]);
        if(k>mid) ret+=qy(k,mid+1,r,rs[a],rs[b],rs[c]);
        return ret;
    }
    void add(int x){
        int k=lower_bound(b+1,b+m+1,a[x])-b;
        rt[x]=rt[f[x]];up(k,1,m,rt[x]);
    }
    void dfs1(int u){
        sz[u]=1;d[u]=d[f[u]]+1;add(u);
        for(pii x:g[u]){
            if(x.fi==f[u]) continue;
            a[x.fi]=x.se;f[x.fi]=u;
            dfs1(x.fi);sz[u]+=sz[x.fi];
            if(sz[x.fi]>sz[son[u]]) son[u]=x.fi;
        }
    }
    void dfs2(int u,int t){
        top[u]=t;
        if(!son[u]) return;
        dfs2(son[u],t);
        for(pii x:g[u]){
            if(x.fi==son[u]||x.fi==f[u]) continue;
            dfs2(x.fi,x.fi);
        }
    }
    int lca(int x,int y){
        while(top[x]!=top[y]){
            if(d[top[x]]>=d[top[y]]) x=f[top[x]];
            else y=f[top[y]];
        }
        if(d[x]>=d[y]) return y;
        else return x;
    }
    int main(){
        scanf("%d%d",&n,&q);
        for(int i=1,a,x,c;i<n;i++){
            scanf("%d%d%d",&a,&x,&c);
            b[++m]=c;
            g[a].pb(pii(x,c));
            g[x].pb(pii(a,c));
        }
        for(int i=1;i<=q;i++){
            scanf("%d%d%d",&qu[i],&qv[i],&qk[i]);
            b[++m]=qk[i];
        }
        sort(b+1,b+m+1);
        m=unique(b+1,b+m+1)-b-1;
        bd(1,m,rt[0]);
        dfs1(1);dfs2(1,1);
        for(int i=1;i<=q;i++){
            qk[i]=lower_bound(b+1,b+m+1,qk[i])-b;
            printf("%d
    ",qy(qk[i],1,m,rt[qu[i]],rt[qv[i]],rt[lca(qu[i],qv[i])]));
        }
        return 0;
    }
    
    
  • 相关阅读:
    海伦公式
    简单的博弈
    Hello World 代码
    Hello world
    99999999海岛帝国后传:算法大会
    判断质数
    idea plantUML配置
    测试用例评审
    如何编写有效测试用例
    测试用例设计——场景分析法
  • 原文地址:https://www.cnblogs.com/xyq0220/p/10911531.html
Copyright © 2020-2023  润新知