zoukankan      html  css  js  c++  java
  • bzoj3631[JLOI2014]松鼠的新家

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3631

    树上差分。

    因为从根到当前点的差分有种种不方便(需要改孩子们的值;需要处理路径上拐出去的其他边等),所以从叶子到根方向地差分!

    注意一下起点不+1,终点+1。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=3e5+5;
    int n,t[N],head[N],xnt,g[N],fa[N][20],dep[N],ans[N];
    struct Edge{
        int next,to;
        Edge(int n=0,int t=0):next(n),to(t) {}
    }edge[N<<1];
    void add(int x,int y)
    {
        edge[++xnt]=Edge(head[x],y);head[x]=xnt;
        edge[++xnt]=Edge(head[y],x);head[y]=xnt;
    }
    void dfs(int cr,int f,int d)
    {
        fa[cr][0]=f;dep[cr]=d;
        for(int i=1;fa[fa[cr][i-1]][i-1];i++)fa[cr][i]=fa[fa[cr][i-1]][i-1];
        for(int i=head[cr];i;i=edge[i].next)
            if(edge[i].to!=f)dfs(edge[i].to,cr,d+1);
    }
    int lg(int a){int cnt;while(a)a>>=1,cnt++;return cnt;}
    void solve(int a,int b)
    {
        g[fa[a][0]]++;g[b]++;
    //    printf("g[%d]=%d g[%d]=%d
    ",a,g[a],b,g[b]);
        if(dep[a]<dep[b])swap(a,b);int d=dep[a]-dep[b],j=0;
        while(d)
        {
            if(d&1)a=fa[a][j];d>>=1;j++;
        }
        if(a==b){g[a]--;g[fa[a][0]]--;return;}
        for(int j=lg(dep[a]);j>=0;j--)
            if(fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
        if(a!=b)a=fa[a][0],b=fa[b][0];
        g[a]--;g[fa[a][0]]--;
    //    printf("g[%d]=%d g[%d]=%d
    ",a,g[a],fa[a][0],g[fa[a][0]]);printf("lca=%d
    ",a);
    }
    int dfs2(int cr,int f)
    {
        int tmp=g[cr];
        for(int i=head[cr],v;i;i=edge[i].next)
            if((v=edge[i].to)!=f)
                tmp+=dfs2(v,cr);
        ans[cr]=tmp;return tmp;
    }
    int main()
    {
        scanf("%d",&n);int x,y;
        for(int i=1;i<=n;i++)scanf("%d",&t[i]);
        for(int i=1;i<n;i++)
            scanf("%d%d",&x,&y),add(x,y);
        dfs(1,0,1);
        for(int i=2;i<=n;i++){
            solve(t[i-1],t[i]);
    //        for(int i=1;i<=n;i++)printf("%d ",g[i]);printf("
    ");
        }
        dfs2(1,0);ans[t[1]]++;ans[t[n]]--;
        for(int i=1;i<=n;i++)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    Linux
    python 鸢尾花数据集报表展示
    python 词云
    毕业设计回顾
    editor.md
    杂记
    垃圾回收器
    杂记
    随笔
    杂记
  • 原文地址:https://www.cnblogs.com/Narh/p/9168053.html
Copyright © 2011-2022 走看看