HDU4008 Parent and son - dfs序/bfs序 - 线段树

传送门

题解:换根操作是老套路,这个有一问是求儿子中的信息,要用bfs序来维护;

要注意的是要求儿子的bfs序和本身并不是连续的。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define MAXN 100010
#define MAXM 200010
#define MAXL 20
#define INF (MAXN-2)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
struct edges{
    int to,pre;
}e[MAXM];
int etop,h[MAXN],dep[MAXN],son[MAXN],L[MAXN];
int in[MAXN],out[MAXN],bin[MAXN],R[MAXN];
inline int add_edge(int u,int v)
{
    etop++;
    e[etop].to=v;
    e[etop].pre=h[u];
    h[u]=etop;
    return 0;
}
int fa[MAXN],up[MAXN][MAXL],times[MAXN],btimes[MAXN];
int bfs_clock,dfs_clock;
inline int dfs(int x,int f)
{
    times[in[x]=++dfs_clock]=x;
    up[x][0]=fa[x]=f;dep[x]=dep[f]+1;
    for(int i=1;i<MAXL;i++)
        up[x][i]=up[up[x][i-1]][i-1];
    for(int i=h[x];i;i=e[i].pre)
        if(e[i].to^fa[x]) dfs(e[i].to,x);
    out[x]=dfs_clock;return 0;
}
queue<int> q;
inline int bfs(int s)
{
    while(!q.empty()) q.pop();
    bin[s]=++bfs_clock;
    q.push(s);btimes[bfs_clock]=s;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=h[x];i;i=e[i].pre)
            if(e[i].to^fa[x])
            {
                bin[e[i].to]=++bfs_clock;
                L[x]=min(L[x],bfs_clock);
                R[x]=max(R[x],bfs_clock);
                son[x]++;btimes[bfs_clock]=e[i].to;q.push(e[i].to);
            }
    }
    return 0;
}
inline int getlx(int x,int y)
{
    for(int i=MAXL-1;i>=0;i--)
        if(dep[up[x][i]]>dep[y])
            x=up[x][i];
    return x;
}
struct segment{
    int l,r,minn,rm;
    segment *ch[2];
}*brt,*rt,pool[MAXN<<2];int pool_top;
inline int push_up(segment* &rt)
{
    rt->minn=min(rt->ch[0]->minn,rt->ch[1]->minn);
    rt->rm=min(rt->ch[0]->rm,rt->ch[1]->rm);
    return 0;
}
inline int build(segment* &rt,int l,int r,int k)
{
    rt=&pool[++pool_top];
    rt->l=l;rt->r=r;
    rt->ch[0]=rt->ch[1]=NULL;
    if(l==r) return rt->minn=rt->rm=(k?times[l]:btimes[r]);
    int mid=(l+r)>>1;
    build(rt->ch[0],l,mid,k);
    build(rt->ch[1],mid+1,r,k);
    push_up(rt);return 0;
}
inline int update(segment* &rt,int s,int t,int v)
{
    int l=rt->l,r=rt->r;
    if(s<=l&&r<=t) return (v^INF)?(rt->minn=rt->rm):(rt->minn=v);
    int mid=(l+r)>>1;
    if(s<=mid) update(rt->ch[0],s,t,v);
    if(mid<t) update(rt->ch[1],s,t,v);
    push_up(rt);return 0;
}
inline int query(segment* &rt,int s,int t)
{
    if(s>t) return INF;
    int l=rt->l,r=rt->r;
    if(s<=l&&r<=t) return rt->minn;
    int mid=(l+r)>>1,ans=INF;
    if(s<=mid) ans=min(ans,query(rt->ch[0],s,t));
    if(mid<t) ans=min(ans,query(rt->ch[1],s,t));
    push_up(rt);return ans;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,q;scanf("%d%d",&n,&q);
        memset(h,0,sizeof(h)),etop=0;
        for(int i=1;i<n;i++)
        {
            int u,v;scanf("%d%d",&u,&v);
            add_edge(u,v),add_edge(v,u);
        }
        int root=1;
        dfs_clock=0;dfs(root,INF);
        memset(son,0,sizeof(son));
        for(int i=1;i<=n;i++) L[i]=INF,R[i]=0;
        bfs_clock=0;bfs(root);
        pool_top=0;build(brt,1,n,0);build(rt,1,n,1);
//        for(int i=1;i<=n;i++) debug(i)sp,debug(in[i])sp,debug(out[i])ln;
//        cout ln;
//        for(int i=1;i<=n;i++) debug(i)sp,debug(bin[i])sp,debug(L[i])sp,debug(R[i])ln;
        while(q--)
        {
            int x,y,c;scanf("%d%d",&x,&y);
            if(x==y)
            {
                if(fa[y]==INF&&!son[y])
                {
                    printf("no answers!\n");
                    continue;
                }
                int ans1=min(fa[y],query(brt,L[y],R[y])),
                    ans2=(y^1)?1:2;
                printf("%d %d\n",ans1,ans2);
            }
            else if(in[y]<=in[x]&&in[x]<=out[y])
            {
                int lx=getlx(x,y);
                if(fa[y]==INF&&son[y]==1)
                {
                    printf("no answers!\n");
                    continue;
                }
                int ans1=min(fa[y],min(query(brt,L[y],bin[lx]-1),query(brt,bin[lx]+1,R[y])));
                update(rt,in[lx],out[lx],INF);update(rt,y,y,INF);int ans2=query(rt,1,n);
                printf("%d %d\n",ans1,ans2);
                update(rt,in[lx],out[lx],0);update(rt,y,y,0);
            }
            else{
//                cout<<"here"<<endl;
                if(!son[y])
                {
                    printf("no answers!\n");
                    continue;
                }
                int ans1=query(brt,L[y],R[y]),ans2=query(rt,in[y]+1,out[y]);
                printf("%d %d\n",ans1,ans2);
            }
        }
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值