LOJ

被一件不愉快的小事浪费了一个小时= =。

表示自己(OI方面的)智商没救了=-=


比较显然 二分+树哈希。考虑对树的括号序列进行哈希。

那么每个点的\(k\)子树的括号序列,就是一段区间去掉距离它为\(k+1\)的点的子树的区间。那么我们把每个点放到它的\(k+1\)级祖先上,在\(k+1\)级祖先处求哈希值时,跳过这个点的括号区间即可。

至于具体的哈希方式...xjb哈希就行了


//672ms	24.97M
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#include <unordered_map>
#define seed 193
#define gc() getchar()
#define MAXIN 500000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
typedef unsigned long long ull;
const int N=1e5+5,M=N<<1; int H[N],nxt[N],L[N],R[N],A[M],mxdep[N];
ull pw[M],hs[M];
std::vector<int> vec[N];
std::unordered_map<ull,bool> vis[18];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
inline void AE(int u,int v)
{
nxt[v]=H[u], H[u]=v;
}
inline ull Hash(int l,int r)
{
return hs[r]-pw[r-l+1]*hs[l-1];
}
void DFS1(int x)
{
static int Index=0;
A[L[x]=++Index]=97; int mx=0;
for(int v=H[x]; v; v=nxt[v]) DFS1(v), mx=std::max(mx,mxdep[v]);
A[R[x]=++Index]=131, mxdep[x]=mx+1;
}
bool DFS2(int x,int k,std::unordered_map<ull,bool> &vis)
{
static int top,sk[N];
sk[++top]=x, std::vector<int>().swap(vec[x]);
if(top>k+1) vec[sk[top-k-1]].push_back(x);
for(int v=H[x]; v; v=nxt[v])
if(DFS2(v,k,vis)) return --top,1;
--top;
if(mxdep[x]<=k) return 0;
int l=L[x],r; ull val=0;
for(auto v:vec[x]) r=L[v]-1, val=val*pw[r-l+1]+Hash(l,r), l=R[v]+1;
r=R[x], val=val*pw[r-l+1]+Hash(l,r);
return vis.count(val)?1:(vis[val]=1,0);
} int main()
{
const int n=read(),n2=n<<1;
for(int i=1; i<=n; ++i)
for(int t=read(); t--; AE(i,read()));//reverse
DFS1(1), pw[0]=1;
for(int i=1; i<=n2; ++i) pw[i]=pw[i-1]*seed, hs[i]=hs[i-1]*seed+A[i];
int l=1,r=n-1,mid,ans=0,t=0;
while(l<=r) DFS2(1,mid=l+r>>1,vis[t++])?(ans=mid,l=mid+1):r=mid-1;
printf("%d\n",ans); return 0;
}

LOJ.6066.[2017山东一轮集训Day3]第二题(树哈希 二分)的更多相关文章

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

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

  2. 【LOJ6067】【2017 山东一轮集训 Day3】第三题 FFT

    [LOJ6067][2017 山东一轮集训 Day3]第三题 FFT 题目大意 给你 \(n,b,c,d,e,a_0,a_1,\ldots,a_{n-1}\),定义 \[ \begin{align} ...

  3. [LOJ#6066]. 「2017 山东一轮集训 Day3」第二题[二分+括号序列+hash]

    题意 题目链接 分析 首先二分,假设二分的答案为 \(mid\),然后考虑利用括号序列来表示树的形态. 点 \(u\) 的 \(k-\) 子树的括号序列表示实际上是刨去了 \(u\) 子树内若干个与 ...

  4. LOJ.6060.[2017山东一轮集训Day1/SDWC2018Day1]Set(线性基)

    LOJ BZOJ 明明做过一道(最初思路)比较类似的题啊,怎么还是一点思路没有. 记所有元素的异或和为\(s\),那么\(x_1+x_2=x_1+x_1\ ^{\wedge}s\). \(s\)是确定 ...

  5. loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)

    题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...

  6. LOJ.6073.[2017山东一轮集训Day5]距离(可持久化线段树 树链剖分)

    题目链接 就是恶心人的,简单写写了...(似乎就是[HNOI2015]开店?) 拆式子,记\(dis_i\)为\(i\)到根节点的路径权值和,\(Ans=\sum dis_{p_i}+\sum dis ...

  7. LOJ.6074.[2017山东一轮集训Day6]子序列(DP 矩阵乘法)

    题目链接 参考yww的题解.本来不想写来但是他有一些笔误...而且有些地方不太一样就写篇好了. 不知不觉怎么写了这么多... 另外还是有莫队做法的...(虽然可能卡不过) \(60\)分的\(O(n^ ...

  8. LOJ.6068.[2017山东一轮集训Day4]棋盘(费用流zkw)

    题目链接 考虑两个\(\#\)之间产生的花费是怎样的.设这之间放了\(k\)个棋子,花费是\(\frac{k(k-1)}{2}\). 在\((r,c)\)处放棋子,行和列会同时产生花费,且花费和该行该 ...

  9. LOJ.6062.[2017山东一轮集训]Pair(Hall定理 线段树)

    题目链接 首先Bi之间的大小关系没用,先对它排序,假设从小到大排 那么每个Ai所能匹配的Bi就是一个B[]的后缀 把一个B[]后缀的匹配看做一条边的覆盖,设Xi为Bi被覆盖的次数 容易想到 对于每个i ...

随机推荐

  1. [算法竞赛入门经典]Ancient Cipher, NEERC 2004,UVa1339

    Description Ancient Roman empire had a strong government system with various departments, including ...

  2. Java 集合系列03之 ArrayList详细介绍

    ArrayList做为List接口中最常用的实现类,必须掌握. 一.ArrayList简介 与Java中的数组相比ArrayList的容量可以动态增加.它继承与AbstractList,实现了List ...

  3. Convolutional Pose Machines(理解)

    0 - 背景 人体姿态识别存在遮挡以及关键点不清晰等主要挑战,然而,人体的关键点之间由于人体结构而具有相互关系,利用容易识别的关键点来指导难以识别关键点的检测,是提高关键点检测的一个思路.本文通过提出 ...

  4. First Unique Character in a String

    Given a string, find the first non-repeating character in it and return it's index. If it doesn't ex ...

  5. osg做的路面项目

  6. MailKit系列之转发电子邮件

    原文:http://www.it1352.com/429181.html 问题 我尝试通过MailKit访问一个IMAP账号,我设法下载邮件(作为的MimeMessage),并在某些时候我需要转发给其 ...

  7. LeetCode.数字转罗马数字

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并 ...

  8. JavaBean与xml互转的方法详解

    本文实例讲述了Jaxb2实现JavaBean与xml互转的方法.分享给大家供大家参考,具体如下: 一.简介 JAXB(Java Architecture for XML Binding) 是一个业界的 ...

  9. js-面试题整理

    var Foo = function(){ getName = function(){alert(1)}; return this; } Foo.getName = function(){alert( ...

  10. OpenGL编程指南(第九版) Tiangles 学习笔记

    ////////////////////////////////////////////////////////////////////////////// // // Triangles.cpp / ...