题意: 给出一些名字,名字间有父子关系,有三种操作:

1.按祖先到后代,兄弟间按字典序由小到大排序,然后输出

2.求某个节点的兄弟节点有多少个,包括自己(注意,根节点的兄弟节点是1)

3.求节点a和b的公共祖先 (注意:如果公共祖先是a或b,必须要输出其父亲,与传统的LCA可以是自己不同)

解法: 先把整棵树整理出来,son[u]表示u的儿子个数,用来求兄弟个数, fa[u]表示父亲,Gson存储儿子的标号,关于排序的问题,先读入所有名字,然后排个序哈希一下,使字典序小的节点标号一定小,那么直接sort(Gson.begin(),Gson.end()) 就将儿子排序了。

然后用RMQ 搞在线LCA 即可

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
using namespace std;
#define N 30107 map<string,int> mp;
int son[N],fa[N],cnt[N];
vector<int> Gson[N];
string TS[N],NS[N];
int ati[],f[],bn,b[],dp[][],ind; void dfs(int u,int dep)
{
for(int i=;i<dep;i++) printf(".");
cout<<NS[u]<<endl;
for(int i=;i<Gson[u].size();i++)
{
int v = Gson[u][i];
dfs(v,dep+);
}
} void init()
{
memset(ati,,sizeof(ati));
memset(f,,sizeof(f));
memset(b,,sizeof(b));
memset(dp,,sizeof(dp));
bn = ind = ;
} void dfs_2(int u,int father)
{
int tmp = ++ind;
f[tmp] = u;
b[++bn] = tmp;
ati[u] = bn;
for(int i=;i<Gson[u].size();i++)
{
int v = Gson[u][i];
if(v==father) continue;
dfs_2(v,u);
b[++bn]=tmp;
}
} void RMQ_init(int n)
{
for (int i=; i<=n; i++) dp[i][]=b[i];
int m=floor(log((double)n*1.0)/log((double)2.0));
for (int j=; j<=m; j++)
for (int i=; i<=n-(<<j)+; i++)
dp[i][j]=min(dp[i][j-],dp[i+(<<(j-))][j-]);
} int RMQ(int l,int r)
{
int k=floor(log((double)r-l+)/log(2.0));
return min(dp[l][k],dp[r-(<<k)+][k]);
} int LCA(int a,int b)
{
if (ati[a] > ati[b]) swap(a,b);
return f[RMQ(ati[a],ati[b])];
} int main()
{
int n,m,i,j;
while(scanf("%d",&n)!=EOF && n)
{
mp.clear();
memset(son,,sizeof(son));
memset(fa,,sizeof(fa));
string ss;
for(i=;i<=n;i++) Gson[i].clear();
for(i=;i<=n;i++)
{
cin>>TS[i];
int len = TS[i].length();
for(j=;j<len;j++)
if(TS[i][j] != '.') break;
NS[i] = TS[i].substr(j,len-j);
}
sort(NS+,NS+n+);
for(i=;i<=n;i++)
mp[NS[i]] = i;
for(i=;i<=n;i++)
{
ss = TS[i];
int len = ss.length();
for(j=;j<len;j++)
if(ss[j] != '.') break;
string S = ss.substr(j,len-j);
cnt[j] = mp[S];
if(j != )
{
fa[mp[S]] = cnt[j-]; //最近的有j-1个'.'的名字就是有j个'.'的名字的父亲
son[cnt[j-]]++;
Gson[cnt[j-]].push_back(mp[S]);
}
else
fa[mp[S]] = ;
}
for(i=;i<=n;i++)
sort(Gson[i].begin(),Gson[i].end());
for(i=;i<=n;i++)
if(fa[i] == ) break;
int father = i;
init();
dfs_2(father,);
RMQ_init(bn);
scanf("%d",&m);
char s[];
while(m--)
{
scanf("%s",s);
if(s[] == 'L')
dfs(father,);
else if(s[] == 'b')
{
cin>>ss;
int k = mp[ss];
if(k == father) puts("");
else printf("%d\n",son[fa[k]]);
}
else
{
string S1,S2;
cin>>S1>>S2;
int ms1 = mp[S1];
int ms2 = mp[S2];
int fat = LCA(ms1,ms2);
if(fat == ms1 || fat == ms2) cout<<NS[fa[fat]]<<endl;
else cout<<NS[fat]<<endl;
}
}
}
return ;
}

HDU 4409 Family Name List --乱搞、LCA的更多相关文章

  1. HDU 1272 小希的迷宫(乱搞||并查集)

    小希的迷宫 Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有 ...

  2. HDU 5938 Four Operations(乱搞)题解

    题意:把'+', '-', '*' 和'/'按顺序插入任意两数字间隔,使得操作得到后计算后最大. 思路:没想到是个水题,打的时候想得太复杂了.这道题其实只要考虑*和/.显然我们要把a*b/c弄到最小. ...

  3. HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题目大意:有n个空花瓶,有两种操作: 操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B ...

  4. hdu 4506 小明系列故事——师兄帮帮忙【幂取模乱搞】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=4506 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  5. hdu 5246 乱搞

    题意:题目太长直接看链接 链接:点我 乱搞题 显然,一个人要想成功,必须大于等于最强的人的战斗力,所以我们从后往前看 这里直接拿例1解释,首先递减排个序 15,13,10,9,8 作差得2,3,1,1 ...

  6. CF809E Surprise me!(莫比乌斯反演+Dp(乱搞?))

    题目大意: 给你一棵树,树上的点编号为\(1-n\).选两个点\(i.j\),能得到的得分是\(\phi(a_i*a_j)*dis(i,j)\),其中\(dis(i,j)\)表示\(a\)到\(b\) ...

  7. 学渣乱搞系列之Tarjan模板合集

    学渣乱搞系列之Tarjan模板合集 by 狂徒归来 一.求强连通子图 #include <iostream> #include <cstdio> #include <cs ...

  8. [WC2018]通道(乱搞,迭代)

    [洛谷题面]https://www.luogu.org/problemnew/show/P4221 这个题以及[CTSC2018 暴力写挂]都有类似的乱搞做法能通过考场数据. 具体搞法就是随一个起点, ...

  9. URAL 1827 Indigenous Wars(排序、乱搞)

    题意:给一个长度为n数组{a[i]}.有m个操作Ti,Si,Li表示找以Ti值结束,以Si值开始,长度为Li的连续子串.找到后,将区间的答案值设为1.一开始答案值全部为0.最后输出n个答案值. 好久没 ...

随机推荐

  1. 【iOS】Quartz2D矩阵操作

    前面画基本图形时,画四边形是由几条直线拼接成的,现在有更简便的方法. 一.关于矩阵操作 1.画一个四边形 通过设置两个端点(长和宽)来完成一个四边形的绘制. 代码: - (void)drawRect: ...

  2. 编写运行R脚本

    1.在后台运行R 1.1 创建file.R文件 1.2 在文件首行键入: #! /path/to/Rscript 1.3 在下面的行中,键入R代码 1.4 保存(记得有png(),jpeg(),... ...

  3. 挖掘机技术哪家强(c++实现)

    描述:为了用事实说明挖掘机技术到底哪家强,组织一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入:输入在第1行给出不超过105的正整数N,即参赛人数.随后N行,每行给出一位参赛者的 ...

  4. elasticsearch分词插件的安装

    IK简介 IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本.最初,它是以开源项目Luen ...

  5. 浅谈React受控与非受控组件

    背景 React内部分别使用了props, state来区分组件的属性和状态.props用来定义组件外部传进来的属性, 属于那种经过外部定义之后, 组件内部就无法改变.而state维持组件内部的状态更 ...

  6. ASP.NET版CKEditor与CKFinder的配置使用

    ASP.NET版 CKEditor与CKFinder的配置使用 将CKEditor 与 CKFinder 的包含在项目中,并添加程序集的引用 从http://cksource.com网站上下载CKEd ...

  7. CSS后代选择器,子选择器和相邻兄弟选择器

    平时在代码练习中,经常用到后代选择器,子选择器也会用到,这里做个总结: 1,后代选择器和子选择器区别: ①写法不一样:后代选择器的标识为:空格 如:ul li{width:150px;} [ul和li ...

  8. Android破解之Lic文件加密程序(首例)

    我不会写Android,这是我第一个破解Android的例子,耗时接近一天,希望大神不要见笑! 本程序为商业软件,不便发布APK程序. 不要给我发消息,我不得回,有问题,直接回帖就可以了. 准备工作 ...

  9. 详解Paint的setPathEffect(PathEffect effect)

    一.setPathEffect() 这个方法一看就和path有关,顾名思义,它就是给path设置样式(效果)的.PathEffect这个路径效果类没有具体的实现,效果是由它的六个子类实现的: 这六个子 ...

  10. 安卓开发_浅谈Android动画(二)

    在学习了四个基本动画之后,现在要学习一些更有用的效果 先给出所有的动画xml <?xml version="1.0" encoding="utf-8"?& ...