HDU 5266 pog loves szh III

来源:互联网 发布:网络射击游戏那个好玩 编辑:程序博客网 时间:2024/05/21 03:25

点击打开链接

一棵树一共有3*10^5个结点,标号为1~N,接下来有3*10^5个询问,给出两个数字L,R,问标号L到R的最近公共祖先是几号结点,默认1号结点为树根。

首先要注意一个问题,这里有10^5数量级的点,如果退化成一条链,在进行dfs的时候就会爆栈,解决方法有3,bfs或者手动dfs或者加黑科技

<span style="font-size:14px;">#pragma comment(linker, "/STACK:102400000,102400000")</span>

注:黑科技只能在C++编译器使用,G++没有这个优化

因为是连续的区间查询,比较容易想到的就是使用线段树来维护,当查询到两个子段时,只要在合并的时候求一下它们的公共祖先即可。每次查询的线段树操作是O(logn)的复杂度,而对于LCA则可以使用在线倍增法。这样查询的过程就是O(log^2n)。

O(n)建树,整个查询为O(Qlog^2n),复杂度为O(Qlog^2n)。大约为10^7~8。

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;#define N 300010#define ls rt<<1#define rs rt<<1|1#define lson l,mid,ls#define rson mid+1,r,rs#pragma comment(linker, "/STACK:102400000,102400000")struct node{    int fa;}Tree[N<<2];vector<int>G[N];int dep[N],fa[N][20];void dfs(int u,int f,int d){     fa[u][0] = f;     dep[u] = d;     for(int i = 0;i<G[u].size();i++){        int v = G[u][i];        if(v!=f){            dfs(v,u,d+1);        }     }}int LCA(int a,int b){    int i,j;    if(a == -1) return b;    if(b == -1) return a;    if(dep[a] < dep[b]) swap(a,b);    for(i = 0;(1<<i) <= dep[a];i++);    i--;    for(j = i;j >= 0;j--)        if(dep[a]-(1<<j)>=dep[b])        a = fa[a][j];    if(a == b) return a;    for(j = i;j >= 0;j--){        if(fa[a][j]!=-1&&fa[a][j]!=fa[b][j]){            a = fa[a][j];            b = fa[b][j];        }    }    return fa[a][0];}void pushup(int rt){     Tree[rt].fa = LCA(Tree[ls].fa,Tree[rs].fa);}void build(int L,int R,int l,int r,int rt){     int mid;     if(l == r){        Tree[rt].fa = l;        return ;     }     mid = (l + r) >> 1;     build(L,R,lson);     build(L,R,rson);     pushup(rt);}int query(int L,int R,int l,int r,int rt){    int mid;    if(L <= l && r <= R){        return Tree[rt].fa;    }    mid = (l + r) >> 1;    int a,b;    a = b = -1;    if(L <= mid) a = query(L,R,lson);    if(R > mid) b = query(L,R,rson);    int ret = LCA(a,b);    return ret;}void init(int n){    memset(fa,-1,sizeof(fa));    for(int i = 0;i <= n+1;i++) G[i].clear();}void init2(int n){     int i,j;     for(int j = 1;(1<<j)<= n;j++){        for(int i = 1;i <= n;i++){            if(fa[i][j-1]!=-1) fa[i][j] = fa[fa[i][j-1]][j-1];        }     }}int main(){    int n,u,v,ans,q;    while(~scanf("%d",&n)){        init(n);        for(int i = 1;i < n;i++){            scanf("%d%d",&u,&v);            G[u].push_back(v);            G[v].push_back(u);        }        dfs(1,1,1);        init2(n);        build(1,n,1,n,1);        scanf("%d",&q);        for(int i = 0;i < q;i++){            scanf("%d%d",&u,&v);            ans = query(u,v,1,n,1);            cout<<ans<<endl;        }    }    return 0;}


0 0
原创粉丝点击