[Explanations] [HNOI2014] World Tree

Face questions

[HNOI2014] World Tree

answer

Readily seen from the data in the range of a virtual tree DP (Unfortunately, I saw it still will not do)

Virtual tree we should be able, if not to their own search, I do not bother to say, and here we only need to consider how to DP

First, we need to find each dot is controlled by which point, let \ (u \) point is \ (bl [u] \) is controlled, twice DFS can be considered the son of his father's influence on his son and father influences

Code details do not believe me, do not solving the problem can not always right DFS

Or stick it out yourself

void dfs1(int u, int fa)
{
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to; if(v == fa) continue; 
        dfs1(v, u); int dv = dep[bl[v]] - dep[u], du = bl[u] ? dep[bl[u]] - dep[u] : 0x3f3f3f3f; 
        if(dv < du || (dv == du && bl[v] < bl[u])) bl[u] = bl[v]; 
    }
}
void dfs2(int u, int fa)
{
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to; if(v == fa) continue; 
        int dv = dis(bl[v], v), du = dis(bl[u], v); 
        if(du < dv || (du == dv && bl[u] < bl[v])) bl[v] = bl[u]; 
        dfs2(v, u); 
    }
}
//分别在递归前和递归后处理一下就完事了

Then consider how to calculate the answer, while the discussion of each virtual tree

①: both the ends is controlled by the same node, with these two points are not in the tree to the imaginary son sz

②: both the ends are different point of control, we need to find a cut-off point to meet this cut-off point return to that point below \ (bl [] \) is controlled, the father of this cut-off point is above that point \ ( BL [] \) is controlled by data structures maintained at or jump multiplying it

As each point is not imaginary tree son sz, sz take the current point of minus all his sons in the virtual tree can sz

Specific implementation details see Code (Ideas reference solution to a problem a bit hey hey hey)

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define N 300005
using namespace std;

int n, m, Q, head[N], sz[N], son[N], dep[N], dfn[N], f[N][21], top[N], cnt, tp, a[N], b[N], stk[N], bl[N], con[N], ans[N], l[N]; 
struct edge { int from, to, next; } e[N << 1]; 

inline int read()
{
    int x = 0, w = 1;
    char c = getchar();
    while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * w;
}

inline void add(int u, int v) { e[++cnt] = (edge) { u, v, head[u] }; head[u] = cnt; }

void dfs_sz(int u, int fa)
{
    sz[u] = 1; dep[u] = dep[fa] + 1; f[u][0] = fa; 
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to; if(v == fa) continue; 
        dfs_sz(v, u); sz[u] += sz[v]; if(sz[son[u]] < sz[v]) son[u] = v; 
    }
}

void dfs_top(int x, int y)
{
    dfn[x] = ++cnt; top[x] = y; 
    if(!son[x]) return; dfs_top(son[x], y); 
    for(int i = head[x]; i; i = e[i].next) if(e[i].to != f[x][0] && e[i].to != son[x]) dfs_top(e[i].to, e[i].to); 
}

int LCA(int x, int y)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]]) swap(x, y); 
        x = f[top[x]][0]; 
    }
    return dep[x] < dep[y] ? x : y; 
}

bool cmp(int x, int y) { return dfn[x] < dfn[y]; }

void dfs1(int u, int fa)
{
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to; if(v == fa) continue; 
        dfs1(v, u); int dv = dep[bl[v]] - dep[u], du = bl[u] ? dep[bl[u]] - dep[u] : 0x3f3f3f3f; 
        if(dv < du || (dv == du && bl[v] < bl[u])) bl[u] = bl[v]; 
    }
}

int dis(int x, int y) { return dep[x] + dep[y] - 2 * dep[LCA(x, y)]; }

void dfs2(int u, int fa)
{
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to; if(v == fa) continue; 
        int dv = dis(bl[v], v), du = dis(bl[u], v); 
        if(du < dv || (du == dv && bl[u] < bl[v])) bl[v] = bl[u]; 
        dfs2(v, u); 
    }
}

void dp(int u)
{
    for(int s, mid, nt, dv, du, i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to; dp(v); s = mid = v;  
        for(int j = l[dep[v]]; j >= 0; j--) if(dep[f[s][j]] > dep[u]) s = f[s][j]; 
        con[u] -= sz[s];
        if(bl[u] == bl[v]) { ans[bl[u]] += sz[s] - sz[v]; continue; }
        for(int j = l[dep[v]]; j >= 0; j--)
        {
            nt = f[mid][j]; if(dep[nt] <= dep[u]) continue; 
            dv = dis(bl[v], nt), du = dis(bl[u], nt); 
            if(dv < du || (dv == du && bl[v] < bl[u])) mid = nt; 
        }
        ans[bl[u]] += sz[s] - sz[mid]; 
        ans[bl[v]] += sz[mid] - sz[v]; 
    }
    ans[bl[u]] += con[u]; 
}

void query()
{
    m = read(); cnt = tp = 0; 
    for(int i = 1; i <= m; i++) bl[a[++cnt] = b[i] = read()] = b[i]; 
    sort(a + 1, a + cnt + 1, cmp); 
    for(int i = 1; i < m; i++) a[++cnt] = LCA(a[i], a[i + 1]); 
    a[++cnt] = 1; sort(a + 1, a + cnt + 1, cmp); 
    int len = unique(a + 1, a + cnt + 1) - a - 1; 
    cnt = 0; for(int i = 1; i <= len; i++) head[a[i]] = 0, con[a[i]] = sz[a[i]]; 
    for(int i = 1; i <= len; i++)
    {
        while(tp && dfn[a[i]] >= dfn[stk[tp]] + sz[stk[tp]]) tp--; 
        if(tp) add(stk[tp], a[i]); stk[++tp] = a[i]; 
    }
    dfs1(1, 0); dfs2(1, 0); dp(1); 
    for(int i = 1; i <= m; i++) printf("%d%c", ans[b[i]], i == m ? '\n' : ' '); 
    for(int i = 1; i <= len; i++) bl[a[i]] = ans[a[i]] = con[a[i]] = 0; 
}

int main()
{
    n = read(); for(int i = 2; i <= n; i++) l[i] = l[i >> 1] + 1; 
    for(int i = 1; i < n; i++) { int u = read(), v = read(); add(u, v); add(v, u); }
    cnt = 0; dfs_sz(1, 0); dfs_top(1, 0); 
    for(int i = 1; i <= n; i++)
        for(int  j = 1; j <= 20; j++) 
            f[i][j] = f[f[i][j - 1]][j - 1]; 
    Q = read(); while(Q--) query(); 
    return 0;
}

Guess you like

Origin www.cnblogs.com/ztlztl/p/10991790.html