Description

幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的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 5

Sample Output

30

HINT

对于所有数据,\(1 \leq n \leq 100000\) , \(1 \leq c \leq 10\)。

对于 \(15%\) 的数据,\(n \leq 2000\)。

另有 \(5%\) 的数据,所有空地都至多与两个空地相邻。

另有 \(5%\) 的数据,除一块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻。

另有 \(5%\) 的数据,除某两块空地与三个空地相邻外,其他空地都分别至多与两个空地相邻。


想法

小数据其实已经提示做法了……

由题意,叶子节点不超过 \(20\) 个。

经过手玩发现,分别以每个叶子节点为根,走到所有点,路径覆盖了所有 点对 之间的路径。

要求本质不同的子串数,这就是广义后缀自动机的模板题了。

啥叫广义后缀自动机?

就是多个字符串可以建在同一个后缀自动机上。

具体方法是,改 \(last\) 的位置。

如插入完一个字符串,再插一个新串时,\(last\) 改到 \(root\)


代码

调了半天,发现 \(insert\) 里少写了一种情况 \(orz...\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring> using namespace std; int read(){
char ch=getchar();
int x=0;
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x;
} const int N = 100005;
typedef long long ll; struct node{
int v;
node *nxt;
}pool[N*2],*h[N];
int cnt;
void addedge(int u,int v){
node *p=&pool[++cnt],*q=&pool[++cnt];
p->v=v;p->nxt=h[u];h[u]=p;
q->v=u;q->nxt=h[v];h[v]=q;
} int n,C;
int col[N],deg[N]; struct trie{
trie *ch[11],*pa;
int len;
}pool2[N*40],*root,*pos[N],*last;
int cnt2;
void insert(int c){
trie *p=last,*cur=&pool2[++cnt2];
cur->len=p->len+1;
for(;p && !p->ch[c];p=p->pa) p->ch[c]=cur;
if(!p) cur->pa=root;
else {
trie *q=p->ch[c],*nq;
if(q->len!=p->len+1){
nq=&pool2[++cnt2];
for(int i=0;i<C;i++) nq->ch[i]=q->ch[i];
nq->len=p->len+1;
nq->pa=q->pa;
q->pa=cur->pa=nq;
for(;p && p->ch[c]==q;p=p->pa) p->ch[c]=nq;
}
else cur->pa=q;
}
last=cur;
} int vis[N];
void dfs(int u){
int v;
vis[u]=1;
for(node *p=h[u];p;p=p->nxt){
if(vis[v=p->v]) continue;
last=pos[u];
insert(col[v]);
pos[v]=last;
dfs(v);
}
} ll dp[N*40];
ll count(trie *p){
if(dp[p-pool2]!=-1) return dp[p-pool2];
dp[p-pool2]=1;
for(int i=0;i<C;i++)
if(p->ch[i]) dp[p-pool2]+=count(p->ch[i]);
return dp[p-pool2];
} int main()
{
int u,v;
n=read(); C=read();
for(int i=1;i<=n;i++) col[i]=read();
for(int i=1;i<n;i++){
u=read(); v=read();
addedge(u,v);
deg[u]++; deg[v]++;
} root=&pool2[++cnt2];
for(int i=1;i<=n;i++){
if(deg[i]!=1) continue;
memset(vis,0,sizeof(vis));
last=root;
insert(col[i]);
pos[i]=last;
dfs(i);
} memset(dp,-1,sizeof(dp));
printf("%lld\n",count(root)-1); return 0;
}

[bzoj3926] [loj2137] [Zjoi2015] 诸神眷顾的幻想乡的更多相关文章

  1. 【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机

    [BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝 ...

  2. bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机)

    bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机) bzoj Luogu 题解时间 给你个无根trie树(你管这叫trie树?),问你选取一条 ...

  3. 【bzoj3926】 Zjoi2015—诸神眷顾的幻想乡

    http://www.lydsy.com/JudgeOnline/problem.php?id=3926 (题目链接) 题意 给出一棵树,每个节点有一个编号,范围在${[0,9]}$.一个序列是指树上 ...

  4. BZOJ3926:[ZJOI2015]诸神眷顾的幻想乡——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3926 https://www.luogu.org/problemnew/show/P3346 幽香 ...

  5. 【bzoj3926】[Zjoi2015]诸神眷顾的幻想乡

    *题目描述: 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也 ...

  6. bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 对[广义后缀自动机]的一些理解

    先说一下对后缀自动机的理解,主要是对构造过程的理解. 构造中,我们已经得到了前L个字符的后缀自动机,现在我们要得到L+1个字符的后缀自动机,什么需要改变呢? 首先,子串$[0,L+1)$对应的状态不存 ...

  7. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1017  Solved: 599[Submit][S ...

  8. 【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 974  Solved: 573 Descriptio ...

  9. 字符串(广义后缀自动机):BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 843  Solved: 510[Submit][St ...

随机推荐

  1. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(11)之支付管理及广告管理

    源码下载地址:http://www.yealuo.com/Sccnn/Detail?KeyValue=c891ffae-7441-4afb-9a75-c5fe000e3d1c 本项目属于个人项目,不支 ...

  2. 一道非常棘手的 Java 面试题:i++ 是线程安全的吗

    转载自  一道非常棘手的 Java 面试题:i++ 是线程安全的吗 i++ 是线程安全的吗? 相信很多中高级的 Java 面试者都遇到过这个问题,很多对这个不是很清楚的肯定是一脸蒙逼.内心肯定还在质疑 ...

  3. Nodejs之使用express框架搭建WEB应用

      首先创建一个index.js,在里面引入相关的中间件,如果没有这些中间件,则需要在nodejs里进入index.js所在的文件夹安装这些模块,安装命令:npm install express ex ...

  4. js算法(2)

    1寻找一个数组中最多的那个数 (1)利用数组 function findMostNum(arr){ var temp1=[];//存放去重的数字 var temp2=[];//存放各个数字的个数 va ...

  5. 牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并)

    牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并) 题意:给你一颗树,要求找出简单路径上最大权值为1~n每个边权对应的最大异或和 题解: 根据异或的性质我们可以得到 \ ...

  6. 很多.net 程序员不知道又非常重要的 .net高级调试技巧.调试别人的dll方法内的变量

    事情是这样的, 最近需要开发Orcale的数据库. 于是使用了EF 加上 Oracle.ManagedDataAccess.Client 这个Oracle.ManagedDataAccess 很好用, ...

  7. [工具] Git版本管理(知识总结)

    对以下文档进行了简要总结,方面复习: [工具] Git版本管理(一)(基本操作) [工具] Git版本管理(二)(分支) [工具] Git版本管理(三)(工作流) [工具] Git版本管理(四)(贡献 ...

  8. 再见,Python2。你好,Python3

     文章首发自我的公众号,转载请注明出处~ ​ Python2的退场,意味着一个时代的结束 ​ 我们这一代程序员基本都接触过python2,很多人也是从python2时代一路走来的.但是,是时候说再见了 ...

  9. 关于SAM和广义SAM

    关于SAM和广义SAM 不是教程 某些思考先记下来 SAM 终于学会了这个东西诶...... 一部分重要性质 确定一个重要事情,S构造出的SAM的一个重要性质是当且仅当对于S的任意一个后缀,可以从1号 ...

  10. Linux 学习笔记 2 Centos 安装与网络的配置以及VI编辑器的使用

    前言 当然,还是觉得Centos 在众多的Linux 发行版中,还是很有地位的,好多的服务器大多沿用的都是一代的Centos 因为它开源(这是废话)而且稳定,这才是服务器沿用的最重要的一项指标. 镜像 ...