码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ5165: 树上倍增

时间:2018-04-09 11:09:26      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:scanf   get   ==   blank   name   题目   algo   script   .com   

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: 树上倍增

标签:scanf   get   ==   blank   name   题目   algo   script   .com   

原文地址:https://www.cnblogs.com/MT-LI/p/8757409.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!