LightOJ1128 Greatest Parent

来源:互联网 发布:淘宝账号注销不了 编辑:程序博客网 时间:2024/06/05 07:28

题面

题意

给出一棵树,每个点都有一个权,每次查询一个点的祖先中比某个数大的最大深度.
已知父节点的权绝对严格小于其子节点

方法

建树之后,利用倍增进行与二分类似的思想进行查找,fa[i][j]记录点i向上(1 << j)代的父亲.
每次查找都找不超过当前范围的最大祖宗.

代码

#include<bits/stdc++.h>#define N 500100using namespace std;int T,TT,n,m,dn[N],fa[N][25],dq,last,ds[N];struct Bn{    int next,to;}bn[200100];inline int find(int l,int r){    last--;    if(l==r||dn[l]>=dq&&dn[fa[l][0]]<dq) return l;    while(fa[l][last]==-1||dn[fa[l][last]]<dn[r])        last--;    if(dn[fa[l][last]]<dq)    {        return find(l,fa[l][last]);    }    else if(dn[fa[l][last]]>dq)    {        return find(fa[l][last],r);    }    return fa[l][last];}int main(){//  freopen("1.txt","r",stdin);//  freopen("2.txt","w",stdout);    int i,j,p,q;    cin>>T;    TT=T;    while(T--)    {        memset(fa,-1,sizeof(fa));        scanf("%d%d",&n,&m);        for(i=1;i<=n-1;i++)        {            scanf("%d%d",&p,&q);            dn[i]=q;            fa[i][0]=p;            ds[p]++;        }        dn[0]=1;        printf("Case %d:\n",TT-T);        for(i=1;i<=20;i++)        {            for(j=0;j<n;j++)            {                if(fa[j][i-1]==-1) continue;                fa[j][i]=fa[fa[j][i-1]][i-1];            }        }        for(i=1;i<=m;i++)        {            scanf("%d%d",&p,&dq);            last=20;            printf("%d\n",find(p,0));        }    }}
原创粉丝点击