hdu 5266 pog loves szh III

给一棵树,q次询问,每次询问给连续的一个闭区间,问区间所有数的LCA是多少。

做一个dfs序,其中把dfs序最小的点和最大的点做一次LCA求出的点就是答案。

 

 

 

 

#include <bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define up rt,rt<<1,rt<<1|1
using namespace std;
const int M = 3e5+7;
int n,q;
int tot,cnt,head[M];
struct edge
{
    int v,next;
}e[M<<1];
void init(){
    tot=cnt=0;memset(head,-1,sizeof(head));
}
void add(int u,int v){
    e[++cnt].v=v;e[cnt].next=head[u];
    head[u]=cnt;
}
int f[M][22],deep[M],in[M];
void dfs(int u,int fa,int d){//dfs(1,-1,0)
    deep[u]=d;
    in[u]=++tot;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u,d+1);
        f[v][0]=u;
    }
    return ;
}
void work(){//RMQ
    for(int i=1;i<20;i++)
        for(int j=1;j<=n;j++) f[j][i]=f[f[j][i-1]][i-1];
}
int lca(int x,int y){//lca
    if(deep[x]<deep[y]) swap(x,y);
    int dt=deep[x]-deep[y];
    for(int i=0;i<20;i++) if(dt&(1<<i)) x=f[x][i];
    if(x==y) return x;
    for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
struct Seg
{
    int mx,mn,mxpos,mnpos;
}seg[M<<2];
void pushup(int rt,int l,int r){
    if(seg[l].mx>seg[r].mx){
        seg[rt].mx=seg[l].mx;seg[rt].mxpos=seg[l].mxpos;
    }
    else{
        seg[rt].mx=seg[r].mx;seg[rt].mxpos=seg[r].mxpos;
    }
    if(seg[l].mn<seg[r].mn){
        seg[rt].mn=seg[l].mn;seg[rt].mnpos=seg[l].mnpos;
    }
    else{
        seg[rt].mn=seg[r].mn;seg[rt].mnpos=seg[r].mnpos;
    }
}
void build(int l,int r,int rt){
    if(l==r){
        seg[rt].mx=seg[rt].mn=in[l];
        seg[rt].mxpos=seg[rt].mnpos=l;
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(up);
}
int query(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        return rt;
    }
    int mid=(l+r)>>1,res=-1;
    if(L<=mid){
        res=query(L,R,lson);
    }
    if(R>mid){
        int tmp=query(L,R,rson);
        if(seg[res].mx<seg[tmp].mx||res==-1) res=tmp;
    }
    return res;
}
int querymn(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        return rt;
    }
    int mid=(l+r)>>1,res=-1;
    if(L<=mid){
        res=querymn(L,R,lson);
    }
    if(R>mid){
        int tmp=querymn(L,R,rson);
        if(seg[res].mn>seg[tmp].mn||res==-1) res=tmp;
    }
    return res;
}
int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    while(~scanf("%d",&n)){
        init();
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        dfs(1,-1,0);
        work();
        build(1,n,1);
        scanf("%d",&q);
        int u,v;
        while(q--){
            scanf("%d%d",&u,&v);if(u>v) swap(u,v);
            int mx=seg[query(u,v,1,n,1)].mxpos,mn=seg[querymn(u,v,1,n,1)].mnpos;
            printf("%d\n",lca(mx,mn));
        }
    }
    return 0;
}
View Code

 

posted @ 2018-09-19 12:10  LMissher  阅读(123)  评论(0编辑  收藏  举报