HDU 6031 Innumerable Ancestors(LCA,树链剖分)

题意: 对于给定的一棵树,树上点的数目为 n ,有 q 次询问,每次给定两个点集 A,B ,求 MAX(LCA(u,v)),uA,vB .其中 k=qi=0(size(A)+size(B))q1e6k1e6,n1e6

思路: 先对树进行剖分,然后将所有 path(u,root),uA 上的树链进行标记,并且记录该树链的最大深度。然后对于每个点 vB ,向 root 找到第一个被标记的树链,并返回 res=MIN(mxdep[x],deep[x]) ,最后 ans=MAX(ans,res)
总的时间复杂度为 T=O(T(2n+2klog(n)))

#include
#include
#include
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define EPS 1e-6
using namespace std;
typedef long long ll;
typedef pair<int, int > pii;

#define sp system("pause")


const int MAXN = 110010;

struct Edge
{
    int to, next;
}edge[MAXN * 2];

int head[MAXN], tot;
int top[MAXN];
int fa[MAXN];
int deep[MAXN];
int num[MAXN];
int son[MAXN];
int pos;
int mrk[MAXN];
int mxdep[MAXN];
int v[MAXN],ttt=0;

void init()
{
    tot = 0;
    memset(head, -1, sizeof head);
    pos = 1;
    memset(son, -1, sizeof son);
}

void addedge(int u, int v)
{
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}

void dfs1(int u, int pre, int d)
{
    deep[u] = d;
    fa[u] = pre;
    num[u] = 1;
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (v == pre)continue;
        dfs1(v, u, d + 1);
        num[u] += num[v];
        if (son[u] == -1 || num[v] > num[son[u]])son[u] = v;
    }
}
void dfs2(int u, int po)
{
    top[u] = po;
    if (son[u] == -1)return;
    dfs2(son[u], po);
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (v != son[u] && v != fa[u])
            dfs2(v, v);
    }
}
int ans = 0;
void lca(int x)
{
    while (x)
    {
        if (mrk[top[x]] == 1 && mxdep[top[x]] == deep[x])break;
        mrk[top[x]] = 1;
        mxdep[top[x]] = max(mxdep[top[x]], deep[x]);
        x = fa[top[x]];
    }
}

int lcb(int x)
{
    while (!mrk[top[x]])x = fa[top[x]];
    return min(mxdep[top[x]], deep[x]);
}

void clr(int x)
{
    while (x)
    {
        if (mrk[top[x]] == 0)break;
        mrk[top[x]] = 0;
        mxdep[top[x]] =0;
        x = fa[top[x]];
    }
}
int main()
{
    int n, m;
    int cot = 0;
    while (scanf("%d%d", &n, &m) != EOF)
    {
        init();
        for (int i = 0; i < n - 1; i++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            addedge(x, y);
            addedge(y, x);
        }
        dfs1(1, 0, 0);
        dfs2(1, 1);
        int mm = 0;
        memset(mrk, 0, sizeof mrk);
        memset(mxdep, 0, sizeof mxdep);
        while (m--)
        {
            //mm++;
            //if (mm >=1)break;
            ttt = 0;
            int x;
            scanf("%d", &x);
            for (int i = 0; i < x; i++)
            {
                int y;
                scanf("%d", &y);
                v[ttt++] = y;
                lca(y);
            }
            scanf("%d", &x);
            ans = 0;
            for (int i = 0; i < x; i++)
            {
                int y;
                scanf("%d", &y);
                ans = max(ans, lcb(y));
            }
            for (int i = 0; i < ttt; i++)clr(v[i]);
            printf("%d\n", ans + 1);
        }
    }
}

你可能感兴趣的:(HDOJ)