秘制 TTT

P1600 [NOIP2016 提高组] 天天爱跑步

Till_Gloam @ 2017-11-06 13:42:42

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 300001
#define M 600001
#define pb push_back
#define For(a, b, c) for(int a = b; a <= (int)(c); ++a)
using namespace std;
int n, m, w[N], ans[N];
inline int read(){
    int u = 0;
    char x = getchar();
    while(x < '0' || x > '9') x = getchar();
    while(x >= '0' && x <= '9') u = (u << 3) + (u << 1) + (x ^ 48), x = getchar();
    return u;
}
int e, be[N], to[M], ne[M];
inline void Add(int u, int v){
    to[++e] = v, ne[e] = be[u], be[u] = e;
}
int dep[N], fa[N], dee[N], son[N];
inline void Dfs1(int x){
    for(int i = be[x]; i; i = ne[i]){
        int v = to[i];
        if(v == fa[x]) continue;
        fa[v] = x, dep[v] = dep[x] + 1;
        Dfs1(v);
        if(dee[v] >= dee[son[x]]) son[x] = v;
    }
    dee[x] = dee[son[x]] + 1;
}
int top[N];
inline void Dfs2(int x, int tp){
    top[x] = tp;
    if(son[x]) Dfs2(son[x], tp);
    for(int i = be[x]; i; i = ne[i])
        if(to[i] != fa[x] && to[i] != son[x])
            Dfs2(to[i], to[i]);
}
inline int LCA(int a, int b){
    while(top[a] != top[b]){
        if(dep[top[a]] < dep[top[b]]) swap(a, b);
        a = fa[top[a]];
    }
    if(dep[a] < dep[b]) swap(a, b);
    return b;
}
vector <int> sa[N], sd[N], na[N], nd[N];
int cov[N];
inline void TAG1(int a, int b){
    int kkk = 0;
    while(top[a] != top[b]){
        if(son[a]) nd[son[a]].pb(kkk - 1);
        kkk += dep[a] - dep[top[a]];
        na[top[a]].pb(kkk);
        a = fa[top[a]], ++kkk;
    }
    if(son[a]) nd[son[a]].pb(kkk - 1);
    kkk += dep[a] - dep[b];
    na[b].pb(kkk);
}
inline void TAG2(int a, int b, int kkk){
    kkk += dep[b] - dep[a];
    while(top[b] != top[a]){
        if(son[b]) sd[son[b]].pb(kkk + 1);
        kkk -= dep[b] - dep[top[b]];
        sa[top[b]].pb(kkk);
        b = fa[top[b]], --kkk;
    }
    if(son[b]) sd[son[b]].pb(kkk + 1);
    kkk -= dep[b] - dep[a];
    sa[a].pb(kkk);
}
int qu[N], cnt, t1[N << 1], t2[N << 1];
bool book[N];
inline void Calc(int x){
    memset(t1, 0, sizeof t1);
    memset(t2, 0, sizeof t2);
    cnt = 0;
    while(x) book[qu[++cnt] = x] = 1, x = son[x];
    int d1 = 1, d2 = n;
    For(i, 1, cnt){
        For(j, 0, na[qu[i]].size() - 1)
            ++t1[d1 + na[qu[i]][j]];
        For(j, 0, nd[qu[i]].size() - 1)
            --t1[d1 + nd[qu[i]][j]];
        For(j, 0, sa[qu[i]].size() - 1)
            ++t2[d2 + sa[qu[i]][j]];
        For(j, 0, sd[qu[i]].size() - 1)
            --t2[d2 + sd[qu[i]][j]];
        ans[qu[i]] = t1[d1 + w[qu[i]]] + t2[d2 + w[qu[i]]] - cov[qu[i]];
        ++d1, --d2;
    }
}
void Get(int x){
    if(!book[x]) Calc(x);
    for(int i = be[x]; i; i = ne[i])
        if(to[i] != fa[x]) Get(to[i]);
}
void Solve(){
    Dfs1(1);
    Dfs2(1, 1);
    while(m--){
        int s = read(), t = read(), ant = LCA(s, t);
        if(s != ant) TAG1(s, ant);
        if(ant != t || s == ant) TAG2(ant, t, dep[s] - dep[ant]);
        if(dep[s] - dep[ant] == w[ant] && s != ant && ant != t) ++cov[ant];
    }
    Get(1);
    For(i, 1, n) printf("%d%c", ans[i], " \n"[i == n]);
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("pro.in", "r", stdin);
    freopen("pro.out","w",stdout);
#endif
    n = read(), m = read();
    For(i, 1, n - 1){
        int u = read(), v = read();
        Add(u, v), Add(v, u);
    }
    For(i, 1, n) w[i] = read();
    Solve();
    return 0;
}

by Till_Gloam @ 2017-11-06 13:43:44

这题不能树剖吗?求大佬~~~


|