松鼠的新家(JLOI2014)

  题目链接:https://www.luogu.org/problemnew/show/P3258

 

  题解: 

  直接树剖,然后维护差分序列。直接线段树维护序列的话复杂度是2个log,用差分的话就是1个log。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define RI register int
using namespace std;
const int INF = 0x7ffffff ;
const int N = 300000 + 10 ;

inline int read() {
    int k = 0 , f = 1 ; char c = getchar() ;
    for( ; !isdigit(c) ; c = getchar())
      if(c == '-') f = -1 ;
    for( ; isdigit(c) ; c = getchar())
      k = k*10 + c-'0' ;
    return k*f ;
}
struct Edge {
    int to, next ;
}e[N<<1] ;
int head[N] ;
inline void add_edge(int x,int y) {
    static int cnt = 0 ;
    e[++cnt].to = y, e[cnt].next = head[x], head[x] = cnt ;
}
int n ; int hh[N] ;

int fa[N], dep[N], son[N], siz[N], top[N], wt[N], id[N] ;
inline void add_wt(int x) {
    static int cnt = 0 ;
    wt[++cnt] = 0, id[x] = cnt ;
}
void dfs1(int x,int f) {
    fa[x] = f, dep[x] = dep[f] + 1, siz[x] = 1 ;
    int y, maxx = 0 ;
    for(int i=head[x];i;i=e[i].next) {
        y = e[i].to ; if(y == f) continue ;
        dfs1(y,x) ;
        if(siz[y] > maxx) {
            maxx = siz[y], son[x] = y ;
        }
        siz[x] += siz[y] ;
    }
}
void dfs2(int x,int topf) {
    add_wt(x) ;
    top[x] = topf ;
    if(!son[x]) return ;
    dfs2(son[x],topf) ;
    int y ;
    for(int i=head[x];i;i=e[i].next) {
        y = e[i].to ;
        if(y == fa[x] || y == son[x]) continue ;
        dfs2(y,y) ;
    }
}
inline void change(int x,int y) {
    while(top[x] != top[y]) {
        if(dep[top[x]] < dep[top[y]]) swap(x,y) ;
        wt[id[top[x]]]++, wt[id[x]+1]-- ;
        x = fa[top[x]] ;
    }
    if(id[x] > id[y]) swap(x,y) ;
    wt[id[x]]++, wt[id[y]+1]-- ;
}

int main() {
    n = read() ;
    for(int i=1;i<=n;i++) hh[i] = read() ;
    int x, y, ans = 0 ;
    for(int i=1;i<n;i++) {
        x = read(), y = read() ;
        add_edge(x,y), add_edge(y,x) ;
    }
    dfs1(1,0) ; dfs2(1,1) ;
    for(int i=1;i<n;i++) {
        change(hh[i],hh[i+1]) ;
        wt[id[hh[i+1]]]--, wt[id[hh[i+1]]+1]++ ;
    }
    x = 0 ;
    for(int i=1;i<=n;i++) wt[i] += wt[i-1] ;
    for(int i=1;i<=n;i++) printf("%d\n",wt[id[i]]) ;
    return 0 ;
}
View Code

 

posted @ 2018-03-13 18:00  zubizakeli  阅读(152)  评论(0编辑  收藏  举报