• [BZOJ3631][JLOI2014]松鼠的新家


    Description

    松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
    可是这样会导致**重复走很多房间,懒惰的**不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。**是个馋家伙,立马就答应了。
    现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。

    Input

    第一行一个整数n,表示房间个数
    第二行n个整数,依次描述a1-an
    接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

    Output

    一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让**有糖果吃。

    Sample Input

    5
    1 4 5 3 2
    1 2
    2 4
    2 3
    4 5

    Sample Output

    1
    2
    1
    2
    1

    HINT

    2<= n <=300000


    非常裸的树上差分。

    注意最后把算了两遍的减1


    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstdlib>
    using namespace std;
    #define reg register 
    inline int read() {
        int res = 0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return res;
    }
    #define N 300005
    
    int n;
    
    struct edge {
        int nxt, to;
    }ed[N*2];
    int head[N], cnt;
    inline void add(int x, int y)
    {
        ed[++cnt] = (edge){head[x], y};
        head[x] = cnt;
    }
    int a[N];
    
    bool vis[N];
    int dep[N];
    int f[N][20];
    
    inline void bfs()
    {
        dep[0] = -1;
        dep[1] = 1;
        queue <int> q;
        q.push(1);
        while(!q.empty())
        {
            int x = q.front();q.pop();
            for (reg int i = head[x] ; i ; i = ed[i].nxt)
            {
                int to = ed[i].to;
                if (dep[to]) continue;
                dep[to] = dep[x] + 1;
                q.push(to);
                f[to][0] = x;
                for (reg int j = 1 ; j <= 19 ; j ++)
                    f[to][j] = f[f[to][j-1]][j-1];
            }
        }
    }
    
    inline int lca(int x, int y)
    {
        if (dep[x] < dep[y]) swap(x, y);
        for (reg int i = 19 ; i >= 0 ; i --)
            if (dep[f[x][i]] >= dep[y]) x = f[x][i];
        if (x == y) return x;
        for (reg int i = 19 ; i >= 0 ; i --)
            if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
        return f[x][0];
    }
    
    int cf[N], ans[N];
    
    void dfs(int x)
    {
        ans[x] = cf[x];
        for (reg int i = head[x] ; i ; i = ed[i].nxt)
        {
            int to = ed[i].to;
            if (to == f[x][0]) continue;
            dfs(to);
            ans[x] += ans[to];
        }
    }
    
    int main()
    {
        n = read();
        for (reg int i = 1 ; i <= n ; i ++) a[i] = read();
        for (reg int i = 1 ; i < n ; i ++)
        {
            int x = read(), y = read();
            add(x, y), add(y, x);
        }
        bfs();
        for (reg int i = 1 ; i <= n - 1 ; i ++)
        {
            int x = a[i], y = a[i+1];
            int l = lca(x, y);
            cf[x]++, cf[y]++;
            cf[l]--, cf[f[l][0]]--;
        }
        dfs(1);
        for (reg int i = 2 ; i <= n ; i ++) ans[a[i]]--; 
        for (reg int i = 1 ; i <= n ; i ++)
            printf("%d
    ", ans[i]);
        return 0;
    }
  • 相关阅读:
    vue-动画
    vue笔记-路由,组件
    自定义键盘信息
    自定义指令
    vue-笔记2
    轻松搭建基于 Serverless 的文档图片在线转换服务
    轻松搭建基于 SpringBoot + Vue 的 Web 商城应用
    一小时快速搭建基于阿里云容器服务-Kubernetes的Web应用
    阿里云正式推出内容平台“云栖号”:全面助力企业和个人上云决策
    云原生安全-更安全的密文管理 Vault on ACK
  • 原文地址:https://www.cnblogs.com/BriMon/p/9603732.html
Copyright © 2020-2023  润新知