【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)
3926: [Zjoi2015]诸神眷顾的幻想乡
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 974 Solved: 573Description
幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日。
粉丝们非常热情,自发组织表演了一系列节目给幽香看。幽香当然也非常高兴啦。这时幽香发现了一件非常有趣的事情,太阳花田有n块空地。在过去,幽香为了方便,在这n块空地之间修建了n-1条边将它们连通起来。也就是说,这n块空地形成了一个树的结构。有n个粉丝们来到了太阳花田上。为了表达对幽香生日的祝贺,他们选择了c中颜色的衣服,每种颜色恰好可以用一个0到c-1之间的整数来表示。并且每个人都站在一个空地上,每个空地上也只有一个人。这样整个太阳花田就花花绿绿了。幽香看到了,感觉也非常开心。粉丝们策划的一个节目是这样的,选中两个粉丝A和B(A和B可以相同),然后A所在的空地到B所在的空地的路径上的粉丝依次跳起来(包括端点),幽香就能看到一个长度为A到B之间路径上的所有粉丝的数目(包括A和B)的颜色序列。一开始大家打算让人一两个粉丝(注意:A,B和B,A是不同的,他们形成的序列刚好相反,比如红绿蓝和蓝绿红)都来一次,但是有人指出这样可能会出现一些一模一样的颜色序列,会导致审美疲劳。于是他们想要问题,在这个树上,一共有多少可能的不同的颜色序列(子串)幽香可以看到呢?太阳花田的结构比较特殊,只与一个空地相邻的空地数量不超过20个。Input
第一行两个正整数n,c。表示空地数量和颜色数量。
第二行有n个0到c-1之间,由空格隔开的整数,依次表示第i块空地上的粉丝的衣服颜色。(这里我们按照节点标号从小到大的顺序依次给出每块空地上粉丝的衣服颜色)。接下来n-1行,每行两个正整数u,v,表示有一条连接空地u和空地v的边。Output
一行,输出一个整数,表示答案。
Sample Input
7 3
0 2 1 2 1 0 0
1 2
3 4
3 5
4 6
5 7
2 5Sample Output
30HINT
对于所有数据,1<=n<=100000, 1<=c<=10。
对于15%的数据,n<=2000。另有5%的数据,所有空地都至多与两个空地相邻。另有5%的数据,除一块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻。另有5%的数据,除某两块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻
叶子节点小于等于20,考虑将每个叶子节点作为根把树给提起来形成一棵trie。(把跟到叶子的路径表示的串放到SAM上)
dfs的时候记录一下它的父亲表示的点在SAM上的位置,把它记为last。
最后统计答案是ans+=step[x]-step[fa[x]]。
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<set>
using namespace std;
#define Maxn 100010
#define LL long long struct node
{
int step,pre,son[];
}t[*Maxn];int tot=;
int last; struct hp
{
int x,y,next;
}a[*Maxn];int al=; int col[Maxn],fa[Maxn],first[Maxn],rd[Maxn]; void ins(int x,int y)
{
a[++al].x=x;a[al].y=y;
a[al].next=first[x];first[x]=al;
} void upd(int x)
{
memset(t[x].son,,sizeof(t[x].son));
t[x].pre=;
} int extend(int k)
{
int np=++tot;upd(tot);
t[np].step=t[last].step+;
int now=last;
while(now&&!t[now].son[k])
{
t[now].son[k]=np;
now=t[now].pre;
}
if(!now) t[np].pre=;
else
{
int p=now,q=t[now].son[k];
if(t[p].step+==t[q].step) t[np].pre=q;
else
{
int nq=++tot;
upd(tot);
memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
t[nq].pre=t[q].pre;
t[q].pre=t[np].pre=nq;
t[nq].step=t[p].step+;
while(now&&t[now].son[k]==q)
{
t[now].son[k]=nq;
now=t[now].pre;
}
}
}
last=np;
return np;
} void dfs(int x,int f)
{
int now=extend(col[x]);
for(int i=first[x];i;i=a[i].next) if(a[i].y!=f)
{
last=now;
dfs(a[i].y,x);
}
} int n,c;
void init()
{
scanf("%d%d",&n,&c);
for(int i=;i<=n;i++) {scanf("%d",&col[i]);col[i]++;}
memset(first,,sizeof(first));
memset(rd,,sizeof(rd));
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
rd[x]++;rd[y]++;
ins(x,y);ins(y,x);
}
t[++tot].step=;
upd(tot);last=;
for(int i=;i<=n;i++) if(rd[i]==)
{
dfs(i,);
last=;
}
} int main()
{
init();
LL ans=;
for(int i=;i<=tot;i++) ans+=t[i].step-t[t[i].pre].step;
printf("%lld\n",ans);
return ;
}
[BZOJ 3926]
2016-09-21 13:33:55
【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)的更多相关文章
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 [广义后缀自动机 Trie]
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1124 Solved: 660[Submit][S ...
- bzoj 3926 [Zjoi2015]诸神眷顾的幻想乡(SAM)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3926 [题意] 给定一棵树,每个节点都有相应的颜色,且保证叶子数不超过20,问 ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串
https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比 ...
- BZOJ.3926.[ZJOI2015]诸神眷顾的幻想乡(广义后缀自动机)
题目链接 要对多个串同时建立SAM,有两种方法: 1.将所有串拼起来,中间用分隔符隔开,插入字符正常插入即可. 2.在这些串的Trie上建SAM.实际上并不需要建Trie,还是只需要正常插入(因为本来 ...
- BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡 ——广义后缀自动机
神奇的性质,叶子节点不超过20个. 然后把这些节点提出来构成一颗新树,那么这些树恰好包含了所有的情况. 所以直接广义后缀自动机. 然后统计本质不同的字符串就很简单显然了. #include <c ...
- bzoj 3926: [Zjoi2015]诸神眷顾的幻想乡【SAM】
有一个显然的性质就是每个串一定在某个叶子为根的树中是一条直的链 然后因为SAM里是不会有相同状态的,所以以每个叶子为根dfs一遍,并且动态构造SAM(这里的节点u的last指向父亲),最后统计答案就是 ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机 多串)
因为任何一条路径都可以看做某两个叶子节点之间路径的一部分,然后分别把20个叶节点当作根,把整棵树看作trie树,那么一条路径就能看作是从根到某个点这一条路的后缀,构建SAM就能维护不同子串的个数了. ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1017 Solved: 599[Submit][S ...
- 字符串(广义后缀自动机):BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 843 Solved: 510[Submit][St ...
- 【刷题】BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡
Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...
随机推荐
- [转]Form中控制Tab画布不同标签间切换的方法
转自:http://yedward.net/?id=68 Form中一般常用的画布类型包括content.stacked.tab这三种,其实content类型的画布是每一个form都必须有的,而且只能 ...
- Java 并发——多线程基础
Thead类与Runnable接口 Java的线程,即一个Thread实例. Java的线程执行过程有两种实现方式: 子类继承Thread类,并且重写void run()方法. 自定义类实现Runna ...
- Ajax.Utility.RegisterTypeForAjax(typeof(_Default)) 的使用
语句的作用:页面注册方法的作用. Ajax.Utility.RegisterTypeForAjax(typeof(命名空间.类名)); 首先要在配置文件里配置 <httpHandlers> ...
- Android XML解析
解析XML有三种方式:Dom.SAX.Pull 其中pull解析器运行方式与SAX类似. 我们首先认识pull解析器:http://developer.android.com/intl/zh-cn/r ...
- Struts1和Struts2的区别和对比(完整版)
Struts2其实并不是一个陌生的Web框架,Struts2是以Webwork的设计思想为核心,吸收了Struts1的优点,因此,可以认为Struts2是Struts1和Webwork结合的产物. 简 ...
- 解决 cocoapods diff: /../Podfile.lock: No such file or directory 问题
解决cocoapods diff: /../Podfile.lock: No such file or directory google一圈之后,找到两个解决方案: 方案一: 关闭Xcode,重新执 ...
- IOS GCD 的理解
GCD (Grand Central Dispatch) 是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式. 在Mac OS X 10.6和IOS 4.0之后开 ...
- swift之元组类型
一.元组类型是有N个任意类型的数据组成(N>=0),组成元组类型的数据可以称为“元素” 二.元组的定义 如:let position = (x:10.5,y:20) //两个元素的元组 l ...
- 原型模式(Prototype Pattern)
原型模型:用于创建重复对象,同时保证性能. 这种模式实现一个原型接口,用于创建对象的克隆,当直接创建对象的代价比较大,则可以采用这种模式.例如:一个对象需要高代价的数据库操作之后被创建,这时可以缓存该 ...
- [CUDA] ubuntu14.04+cuda7.5下安装cudnn7.0
cuda:7.5 cudnn:cudnn-7.0-linux-x64-v4.0-prod.tgz cudnn样例:cuDNN v4 Code Samples 1. 解压 tar -zxvf cudnn ...