Description

对于一棵有根树,定义一个点u的k-子树为u的子树中距离u不超过k的部分。
注意,假如u的子树中不存在距离u为k的点,则u的k-子树是不存在的。
定义两棵子树是相同的,当且仅当不考虑点的标号时,他们的形态是
相同的(儿子的顺序也需要考虑)。给定一棵n个点,点的标号在[1,n],
以1为根的有根树。问最大的k,使得存在两个点u !=v,满足u的k-子树与v的k-子树相同。

Input

第一行输入一个正整数n。
接下来读入n个部分,第i个部分描述点i的儿子,且以顺序给出。
每个部分首先读入一个整数x,代表儿子个数。
接下来x个整数,代表从左到右儿子的标号
n ≤ 100000,保证给出的树是合法的

Output

输出一个整数k,代表最大的合法的k
已知每个点的a-子树和b-子树的hash,可以推出每个点的(a+b)-子树的hash
对答案倍增,hash判定
#include<cstdio>
#include<cstring>
#define Fe(i,l,r) for(int i=l;i<=r;++i)
typedef unsigned long long u64;
const int N=,P=;
void maxs(int&a,int b){if(a<b)a=b;}
u64 H(u64 x){return (x^x>>^x<<)+;}
char buf[],*ptr=buf+;
int G(){
if(ptr-buf==)fread(ptr=buf,,,stdin);
return *ptr++;
}
int _(){
int x=;
if(ptr-buf<){
while(*ptr<)++ptr;
while(*ptr>)x=x*+*ptr++-;
}else{
int c=G();
while(c<)c=G();
while(c>)x=x*+c-,c=G();
}
return x;
}
int n,ans=;
int mem[N],*mp=mem,*e[N],ep[N],fa[][N],fas[N],id[N],_fa[N],_son[N];
int q[N],ql=,qr=,dep[N],md[N];
u64 h[][N],h2[N],_h[N];
u64 hx[P];
int ht[P],tk=;
bool ins(u64 x){
int w=(unsigned(x)^unsigned(x>>))%P;
while(ht[w]==tk){
if(hx[w]==x)return ;
if((w+=)>=P)w-=P;
}
hx[w]=x;ht[w]=tk;
return ;
}
template<class T>
void cpy(T*a,T*b){memcpy(a+,b+,sizeof(T)*n);}
void getson(){
memset(_son+,,sizeof(int)*n);
Fe(t,,qr){
int w=q[t],f=fas[w];
if(!_son[f])_son[f]=t;
}
}
void cal(int _i){
cpy(_h,h[_i]);
cpy(_fa,fa[_i]);
for(int i=_i-;i>=;--i){
++tk;
cpy(h2,_h);
getson();
Fe(t,,qr){
int w=q[t],f=_fa[w];
if(f)h2[f]=h2[f]*+h[i][w]+(id[fa[][w]]-_son[f]);
}
bool is=;
int mn=ans+(<<i);
Fe(w,,n)if(md[w]+>=mn&&ins(h2[w])){
is=;
break;
}
if(is){
ans=mn;
Fe(w,,n){
_h[w]=H(h2[w]);
_fa[w]=fa[i][_fa[w]];
fas[w]=fa[i][fas[w]];
}
}
}
}
void cal(){
Fe(w,,n)h[][w]=;
for(int i=;i<;++i){
++tk;
cpy(h2,h[i]);
getson();
Fe(t,,qr){
int w=q[t],f=fa[i][w];
if(f)h2[f]=h2[f]*+h[i][w]+(id[fa[][w]]-_son[f]);
}
bool is=;
int mn=ans+(<<i);
Fe(w,,n)if(md[w]+>=mn&&ins(h2[w])){
is=;
break;
}
if(is){
ans=mn;
Fe(w,,n){
h[i+][w]=H(h2[w]);
fa[i+][w]=fa[i][fa[i][w]];
fas[w]=fa[i][fas[w]];
}
}else return cal(i);
}
}
int main(){
n=_();
for(int i=;i<=n;++i){
fas[i]=i;
e[i]=mp;
mp+=ep[i]=_();
for(int j=;j<ep[i];++j)fa[][e[i][j]=_()]=i;
}
for(q[++qr]=;fa[][q[]];++q[]);
while(ql!=qr){
int w=q[++ql];
id[w]=ql;
for(int*l=e[w],*r=l+ep[w];l!=r;++l)dep[q[++qr]=*l]=dep[w]+;
}
for(int i=qr;i;--i){
int w=q[i];
maxs(md[fa[][w]],md[w]+);
}
cal();
printf("%d\n",ans-);
return ;
}

bzoj4928: 第二题的更多相关文章

  1. 【BZOJ4928】第二题 树hash+倍增

    [BZOJ4928]第二题 Description 对于一棵有根树,定义一个点u的k-子树为u的子树中距离u不超过k的部分. 注意,假如u的子树中不存在距离u为k的点,则u的k-子树是不存在的. 定义 ...

  2. 05:统计单词数【NOIP2011复赛普及组第二题】

    05:统计单词数 总时间限制:  1000ms 内存限制:  65536kB 描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次 ...

  3. 常见面试第二题之什么是Context

    今天的面试题,也就是我们常见面试题系列的第二题,我们来讲一讲android中的context.我相信大家android开发者一定对于这个context非常熟悉,肯定都有使用过,肯定没有没使用过的.但是 ...

  4. 《学习OpenCV》练习题第五章第二题abc

    代码: #include <stdio.h> #include <opencv/highgui.h> #include <opencv/cv.h> #include ...

  5. 《学习OpenCV》练习题第四章第二题

    #include <highgui.h> #include <cv.h> #pragma comment (lib,"opencv_calib3d231d.lib&q ...

  6. CSDN挑战编程——《金色十月线上编程比赛第二题:解密》

    金色十月线上编程比赛第二题:解密 题目详情: 小强是一名学生, 同一时候他也是一个黑客. 考试结束后不久.他吃惊的发现自己的高等数学科目竟然挂了,于是他果断入侵了学校教务部站点. 在入侵的过程中.他发 ...

  7. NOIP2005-普及组复赛-第二题-校门外的树

    题目描述 Description 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0 ...

  8. 【gdoi2018 day2】第二题 滑稽子图(subgraph)(性质DP+多项式)

    题目大意 [gdoi2018 day2]第二题 滑稽子图(subgraph) 给你一颗树\(T\),以及一个常数\(K\),对于\(T\)的点集\(V\)的子集\(S\). 定义\(f(S)\)为点集 ...

  9. 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)

    [LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...

随机推荐

  1. bzoj1002

    题解: f[i]=(f[i-1]*3+f[i-2]); 高精度计算 代码: #include<bits/stdc++.h> using namespace std; struct big ...

  2. windowns 下备份mysql数据库

    @echo off & setlocal ENABLEEXTENSIONS :: ---------- 配置项 ---------- :: 备份放置的路径,加 \ set BACKUP_PAT ...

  3. 使用ALVideoPlayerSurface制作视频播放器

    头两天介绍了开源控件包alcinoe,现在利用其中的ALVideoPlayerSurface视频播放控件,实作一个视频播放器. 首先,建一个fmx项目,然后从组件面版,拖放一个TAlVideoPlay ...

  4. pseudo tty破除无法自动输入密码的限制

    没有root权限,没有ssh密钥对,又想自动输入密码咋办? #!/usr/bin/python # simplest builtin python pseudo-tty for ssh passwor ...

  5. linux 优化git操作速度

    修改 ssh配置:useDNS:no

  6. vue 移动端添加 时间日期选择器

    效果: index.vue <template> <div class="user-wrap" style="padding-bottom: 0;tex ...

  7. 新手小白Linux(Centos6.5)部署java web项目(mysql5.7安装及相关操作)

    一.安装 参考:https://dev.mysql.com/doc/refman/5.7/en/linux-installation-yum-repo.html # 检测系统中是否安装了mysql y ...

  8. C高级第一次PTA作业

    作业要求一 附加题目 写程序证明P++等价于(p)++还是等价于*(p++)? 1.设计思路: (1).题目算法描述 第一步:定义变量p并赋初值 第二步:分三次计算每次分别输出 p++,(p)++,* ...

  9. jsp之response方法

    response简介 response对象:对客户端的请求作出回应,将Web服务器处理后的结果发回客户端. response对象:属于javax.servlet.HttpServletResponse ...

  10. 定义一组抽象的 Awaiter 的实现接口,你下次写自己的 await 可等待对象时将更加方便

    我在几篇文章中都说到了在 .NET 中自己实现 Awaiter 情况.async / await 写异步代码用起来真的很爽,就像写同步一样.然而实现 Awaiter 没有现成的接口,它需要你按照编译器 ...