• [JLOI2014]松鼠的新家 倍增LCA+树上差分


    题目描述
    题目

    本来想写一道Tarjan的,结果发现这题倍增比较好写
    这题主要要搞懂树上差分这东西(NOIP前这东西卡了我好久)
    大概要注意的就是对于除了出发点以外的所有点都是重复算了的,所以最后要有-1操作

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=300010;
    int f[N][20],head[N],a[N],b[N],dep[N];
    int now,n;
    struct E{int to,next;}e[N<<1];
    void build(int u,int v){e[++now].to=v;e[now].next=head[u];head[u]=now;}
    
    void dfs1(int u,int fa)
    {
        f[u][0]=fa;
        for(int i=1;f[u][i-1];i++) f[u][i]=f[f[u][i-1]][i-1];
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v == fa) continue;
            dep[v]=dep[u]+1;
            dfs1(v,u);
        }
    }
    
    int lca(int u,int v)
    {
        if(dep[u] > dep[v]) swap(u,v);
        int d=dep[v]-dep[u];
        for(int i=0;(1<<i) <= d;i++)
            if((1<<i) & d) v=f[v][i];
        if(u == v) return u;
        for(int i=19;i >= 0;i--)
            if(f[u][i] != f[v][i])
                u=f[u][i],v=f[v][i];
        return f[u][0];
    }
    
    int read(){
        int out=0;char c=getchar();while(c > '9' || c < '0') c=getchar();
        while(c >= '0' && c <= '9') {out=(out<<1)+(out<<3)+c-'0';c=getchar();}return out;
    }
    
    void init()
    {
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<n;i++) {int u=read(),v=read();build(u,v);build(v,u);}
        dfs1(1,0);
    }
    
    void dfs2(int u)
    {
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v == f[u][0]) continue;
            dfs2(v);
            b[u]+=b[v];
        }
    }
    
    void solve()
    {
        for(int i=2;i<=n;i++)
        {
            int u=a[i-1],v=a[i],glca=lca(u,v);
            b[u]++;b[v]++;b[f[glca][0]]--;b[glca]--;
        }
        dfs2(1);
        for(int i=2;i<=n;i++) b[a[i]]--;
        for(int i=1;i<=n;i++) printf("%d
    ",b[i]);
    }
    
    int main()
    {
        init();
        solve();
        return 0;
    }
    
  • 相关阅读:
    MyEclipse中快速查看错误
    MyEclipse中快速跳转到指定行号位置
    MyEclipse关闭当前正在编辑的页面
    dict、defaultdict 和 OrderedDict 比较
    过滤器的使用
    cookie和session
    session的使用
    Java的常量和变量
    Java面向对象
    Java方法
  • 原文地址:https://www.cnblogs.com/zerolt/p/9260895.html
Copyright © 2020-2023  润新知