BZOJ3572/Luogu3233 [Hnoi2014]世界树 (虚树) (Unfinished)

本文介绍了一种基于LCA算法解决树上路径查询问题的方法,并通过离线处理多个查询来提高效率。文中详细展示了如何构建树状结构、进行DFS遍历及离线处理查询请求的过程。此外,还提供了完整的C++代码实现。

我太弱了,这叼题先搁着把,来日方长,自有切时。。。

。。。或许吧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int  a = (b); a <= (c); ++ a)
#define nR(a,b,c) for(register int  a = (b); a >= (c); -- a)
#define Max(a,b) ((a) > (b) ? (a) : (b))
#define Min(a,b) ((a) < (b) ? (a) : (b))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) a^=b^=a^=b
#define ll long long
#define ON_DEBUG

#ifdef ON_DEBUG

#define D_e_Line printf("\n\n----------\n\n")
#define D_e(x)  cout << #x << " = " << x << endl
#define Pause() system("pause")

#else

#define D_e_Line ;

#endif

struct ios{
    template<typename ATP>ios& operator >> (ATP &x){
        x = 0; int f = 1; char c;
        for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-')  f = -1;
        while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
        x*= f;
        return *this;
    }
}io;
using namespace std;
#include <vector>

const int N = 300007;

int n;
int ans[N];

struct Edge{
    int nxt, pre, w;
}e[N << 1];
int head[N], cntEdge;
inline void add(int u, int v, int w){
    e[++cntEdge] = (Edge){head[u], v, w}, head[u] = cntEdge;
}

vector<int> G[N];

int dis[N];

int fa[N], son[N], dep[N], siz[N];
inline void DFS_First(int u, int father){
    fa[u] = father, dep[u] = dep[father] + 1, siz[u] = 1;
    for(register int i = head[u]; i; i = e[i].nxt){
        int v = e[i].pre;
        if(v == father) continue;
        dis[v] = dis[u] + e[i].w;
        DFS_First(v, u);
        siz[u] += siz[v];
        if(!son[u] || siz[v] > siz[son[u]]){
            son[u] = v;
        }
    }
}
int dfn[N], dfnIdx, top[N];
inline void DFS_Second(int u, int ancester){
    top[u] = ancester, dfn[u] = ++dfnIdx;
    if(!son[u]) return;
    DFS_Second(son[u], ancester);
    for(register int i = head[u]; i; i = e[i].nxt){
        int v = e[i].pre;
        if(v != son[u] && v != fa[u]){
            DFS_Second(v, v);
        }
    }
}
inline int LCA(int x, int y){
    while(top[x] != top[y]){
        if(dep[fa[top[x]]] < dep[top[y]]) Swap(x, y);
        x = fa[top[x]];
    }
    return dep[x] < dep[y] ? x : y;
}

int sta[N], _top;
inline void Insert(int x){
    if(_top < 2){
        sta[++_top] = x;
        return;
    }
    int lca = LCA(x, sta[_top]);
    if(lca == sta[_top]){
        sta[++_top] = x;
        return;
    }
    while(_top > 1 && dfn[sta[_top-1]] >= dfn[lca]){
        G[sta[_top - 1]].push_back(sta[_top]);
        -- _top;
    }
    if(lca != sta[_top]){
        G[lca].push_back(sta[_top]);
        sta[_top] = lca;
    }
    sta[++_top] = x;
}

inline void DFS(){
    
}

int a[N];
inline bool cmp(const int &a, const int &b){
    return dfn[a] < dfn[b];
}
int main(){
    io >> n;
    R(i,2,n){
        int u, v;
        io >> u >> v;
        add(u, v, 1);
        add(v, u, 1);
    }
    
    DFS_First(1, 0);
    DFS_Second(1, 1);
    
    int Tasks;
    io >> Tasks;
    while(Tasks--){
        int m;
        io >> m;
        R(i,1,m){
            io >> a[i];
        }
        sort(a + 1, a + m + 1, cmp);
        
        R(i,1,m) Insert(a[i]);
        while(_top > 1){
            G[sta[_top - 1]].push_back(sta[_top]);
            -- _top;
        }
        
        DFS(1);
        
        R(i,1,m){
            printf("%d ", ans[i]);
        }
        putchar('\n');
        
    }
    
    return 0;
}

1570282-20190719205921801-1846713310.png

转载于:https://www.cnblogs.com/bingoyes/p/11215705.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值