BZOJ5165: 树上倍增

Posted mt-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ5165: 树上倍增相关的知识,希望对你有一定的参考价值。

Description

现有一棵树。您需要写一个树上倍增算法,以实现如下操作:
A x 新建一个节点,将它作为x节点的儿子,编号为当前节点总数+1。
Q k p1 p2 p3.... 查询p1,p2,p3...这些节点的LCA。其中k表示查询节点的个数。
最初树上只有一个节点,编号为1。 
多个节点的LCA定义为:这些节点的公共祖先中深度最大的。
 

 

Input

第一行,一个正整数,表示操作个数。 
接下来行,每行输入一个操作,格式如题目描述所述。
保证任何输入的数都是正整数。
n≤3000000 k≤1000。
保证询问不超过1000次
 

 

Output

对于每一个Q操作,输出一行一个正整数,表示所询问节点的LCA。
 

 

Sample Input

10
A 1
A 2
A 3
A 1
A 5
A 5
Q 2 3 6
Q 2 6 7
Q 2 4 2
Q 3 7 6 5

Sample Output

1
5
2
5
解释
3,6的LCA是1。
6,7的LCA是5。
4,2的LCA是2。
7,6,5的LCA是5。
 
 
疯了这道题还卡我空间。。f**k,出题人%^#&$#^#!#@$^&#*
他说LCA就LCA啊,没什么改变。。
多点LCA??我不会。。
Rose说就是一个贪心,你一直往上跳,看看行不行即可
至于时间。。25s的题也就那样。。。
 
代码如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int bin[25],fa[3000010][21],dep[3000100];
int n,Q,m;
char st[51];
int a[3100];
bool cmp(int x,int y){return dep[x]>dep[y];}
bool check(int j)
{
    for(int i=1;i<m;i++)if(fa[a[i]][j]!=fa[a[i+1]][j])return true;
    return false;
}
int main()
{
    scanf("%d",&Q);
    bin[0]=1;for(int i=1;i<=24;i++)bin[i]=bin[i-1]<<1;
    dep[1]=1;fa[1][0]=0;n=1;
    while(Q--)
    {
        scanf("%s%d",st+1,&m);
        if(st[1]==A)
        {
            n++;int f=m;
            dep[n]=dep[f]+1;fa[n][0]=f;
            for(int i=1;bin[i]<=dep[n];i++)fa[n][i]=fa[fa[n][i-1]][i-1];
        }
        else
        {
            for(int i=1;i<=m;i++)scanf("%d",&a[i]);
            sort(a+1,a+1+m,cmp);
            for(int i=20;i>=0;i--)
                for(int j=1;j<m;j++)
                    if(bin[i]<=dep[a[j]]&&dep[fa[a[j]][i]]>=dep[a[m]])a[j]=fa[a[j]][i];
            bool bk=true;
            for(int i=2;i<=m;i++)if(a[i]!=a[i-1]){bk=false;break;}
            if(bk==true){printf("%d\n",a[1]);continue;}
            for(int i=20;i>=0;i--)
                if(bin[i]<=dep[a[1]]&&check(i)==true)
                    for(int j=1;j<=m;j++)
                        a[j]=fa[a[j]][i];
            printf("%d\n",fa[a[1]][0]);
        }
    }
    return 0;    
}

by_lmy

以上是关于BZOJ5165: 树上倍增的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3551[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

BZOJ-4281Zwi?zek Harcerstwa Bajtockiego 树上倍增LCA

bzoj3306: 树(dfs序+倍增+线段树)

bzoj 3569 DZY Loves Chinese II 随机算法 树上倍增

bzoj4281[ONTAK2015]Zwi?zek Harcerstwa Bajtockiego 树上倍增+LCA

bzoj3779重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询