zoukankan      html  css  js  c++  java
  • bzoj 3631 松鼠的新家 (树链剖分)

    链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3631

    思路:

    直接用树链剖分求每一次运动,因为这道题只需要区间增添,单点求值,没必要用线段树,直接数组标记下就好了

    实现代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid int m = (l + r) >> 1
    
    const int M = 1e5 + 10;
    int cnt,cnt1;
    int head[M],dep[M],fa[M],top[M],son[M],siz[M],tid[M],sum[M],a[M];
    
    struct node{
        int to,next;
    }e[M];
    
    void add(int u,int v){
        e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
    }
    
    void dfs1(int u,int faz,int deep){
        dep[u] = deep;
        fa[u] = faz;
        siz[u] = 1;
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v == fa[u]) continue;
            dfs1(v,u,deep+1);
            siz[u] += siz[v];
            if(siz[v] > siz[son[u]]||son[u] == -1)
                son[u] = v;
        }
    }
    
    void dfs2(int u,int t){
        top[u] = t;
        tid[u] = ++cnt1;
        if(son[u] == -1) return ;
        dfs2(son[u],t);
        for(int i = head[u];i;i=e[i].next){
            int v = e[i].to;
            if(v != fa[u]&&v != son[u])
                dfs2(v,v);
        }
    }
    
    void update(int x,int y){
        sum[x]++;
        sum[y+1]--;
    }
    
    void solve(int x,int y){
        int fx = top[x],fy = top[y];
        int ans = 0;
        while(fx!=fy){
            if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
            update(tid[fx],tid[x]);
            x = fa[fx]; fx = top[x];
        }
        if(dep[x] > dep[y]) swap(x,y);
        update(tid[x],tid[y]);
    }
    
    int main(){
        int n,x,y;
        scanf("%d",&n);
        memset(son,-1,sizeof(son));
        for(int i = 1;i <= n;i ++){
            scanf("%d",&a[i]);
        }
        int n1 = n-1;
        while(n1--){
            scanf("%d%d",&x,&y);
            add(x,y); add(y,x);
        }
        dfs1(1,0,1); dfs2(1,0);
        for(int i = 2;i <= n;i ++)
            solve(a[i-1],a[i]);
        for(int i = 1;i <= n;i ++){
            sum[i] += sum[i-1];
        }
       // cout<<1<<endl;
        for(int i = 1;i <= n;i ++){
            if(i == 1) printf("%d
    ",sum[tid[i]]);
            else printf("%d
    ",sum[tid[i]]-1);
        }
        return 0;
    }
  • 相关阅读:
    常量与变量
    BandicamPortable破解软件的按照和设置
    普罗米修斯监控马哥亲自讲解
    为什么需要监控,在哪些层次上监控,监控什么
    prometheus比zabbix好在哪点?
    聊一聊几款流行监控系统,你知道几个?
    监控系统选型看这一篇够了!选择 Prometheus 还是 Zabbix ?
    DNS详细解析问题
    洛谷 P4025 [PA2014]Bohater(贪心)
    洛谷 P1842 [USACO05NOV]奶牛玩杂技(贪心)
  • 原文地址:https://www.cnblogs.com/kls123/p/9806960.html
Copyright © 2011-2022 走看看