码迷,mamicode.com
首页 > 其他好文 > 详细

HdU5266(LCA + 线段树)

时间:2015-06-22 06:27:55      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:数据结构   lca   线段树   

pog loves szh III

 
 Accepts: 63
 
 Submissions: 483
 Time Limit: 12000/6000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
pog在与szh玩游戏,首先pog在纸上画了一棵有根树,这里我们定义1为这棵树的根,然后szh在这棵树中选了若干个点,想让pog帮忙找找这些点的最近公共祖先在哪里,一个点为S的最近公共祖先当且仅当以该点为根的子树包含S中的所有点,且该点深度最大。然而,这个问题是十分困难的,出于szh对pog的爱,他决定只找编号连续的点,即li~ri
输入描述
若干组数据(不超过3n10000Q10000)。
每组数据第一行一个整数n(1n300000),表示树的节点个数。
接下来n?1行,每行两个数AiBi,表示存在一条边连接这两个节点。
接下来一行一个数Q(1Q300000),表示有Q组询问。
接下来Q行每行两个数li,ri(1lirin),表示询问编号为li~ri的点的最近公共祖先。
输出描述
对于每组的每个询问,输出一行,表示编号为li~ri的点的最近公共祖先的编号。
输入样例
5
1 2
1 3
3 4
4 5
5
1 2
2 3
3 4
3 5
1 5
输出样例
1
1
3
3
1
Hint
珍爱生命,远离爆栈。

预处理之后LCA是O(1)的,然后用线段树就能在logn的时间里得出询问结果啦!


#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 3e5 + 10;
const int inf = 1e8;
int pos[maxn],depth[maxn],head[maxn];
int d[maxn<<1][20],width[maxn<<1],tot,e;
typedef pair<int,int> Edge;
Edge edges[maxn<<1];
void AddEdge(int u,int v)
{
    edges[++e] = make_pair(v,head[u]);head[u] = e;
    edges[++e] = make_pair(u,head[v]);head[v] = e;
}
void pre(int u,int fa,int dep = 0)
{
    d[++tot][0] = u;
    if(!pos[u]) {
        pos[u] = tot;
        depth[u] = dep; 
    }
    for(int eid = head[u]; eid ; eid = edges[eid].second) {
        int &v = edges[eid].first;
        if(v==fa)continue;
        pre(v,u,dep+1);
        d[++tot][0] = u;
    }
}
void RMQ_init(int n)
{
    for(int j = 1; (1<<j) <= n; j++) {
        for(int i = 1; i + (1<<j) - 1 <= n; i++) {
            d[i][j] = depth[d[i][j-1]] < depth[d[i+(1<<(j-1))][j-1]] ? d[i][j-1] : d[i+(1<<(j-1))][j-1];
        }
    }
    for(int i = 1,w = 1; i <= n; i++) {
        if((1<<w) <= i) w++;
        width[i] = w;
    }
}
int LCA(int u,int v)
{
    int L = pos[u],R = pos[v];
    if(L > R) swap(L,R);
    int k = width[R-L+1] - 1;
    return depth[d[L][k]] < depth[d[R-(1<<k)+1][k]] ? d[L][k] : d[R-(1<<k)+1][k];
}
int seg[maxn<<1];
void built(int o,int L,int R)
{
    if(L==R) {
        seg[o] = L;
        return;
    }
    int mid = (L + R) >> 1;
    built(o<<1,L,mid);
    built(o<<1|1,mid+1,R);
    seg[o] = LCA(seg[o<<1],seg[o<<1|1]);
}
int ql,qr;
int Query(int o,int L,int R)
{
    if(ql<=L&&qr>=R) {
        return seg[o];
    }
    int mid = (L + R) >> 1;
    int ans = -1;
    if(ql <= mid) ans = Query(o<<1,L,mid);
    if(qr > mid) {
        int t = Query(o<<1|1,mid+1,R);
        if(ans==-1) ans = t;
        else ans = LCA(ans,t);
    }
    return ans;
}
int main(int argc, char const *argv[])
{
    int n;
    while(scanf("%d",&n)==1) {

        memset(head,0,sizeof(head[0])*(n+1));
        for(int i = 1; i < n; i++) {
            int u, v;scanf("%d%d",&u,&v);
            AddEdge(u,v);
        }
        e = tot = 0;
        memset(pos,0,sizeof(pos[0])*(n+1));
        pre(1,-1);
        RMQ_init(tot);
        built(1,1,n);
        int Q;scanf("%d",&Q);
        while(Q--) {
            scanf("%d%d",&ql,&qr);
            if(ql > qr) swap(ql,qr);
            printf("%d\n", Query(1,1,n));
        } 
    }
    return 0;
}

HdU5266(LCA + 线段树)

标签:数据结构   lca   线段树   

原文地址:http://blog.csdn.net/acvcla/article/details/46586911

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!