[BZOJ3926][Zjoi2015]诸神眷顾的幻想乡
试题描述
幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日。
输入
第一行两个正整数n,c。表示空地数量和颜色数量。
输出
一行,输出一个整数,表示答案。
输入示例
7 3 0 2 1 2 1 0 0 1 2 3 4 3 5 4 6 5 7 2 5
输出示例
30
数据规模及约定
对于所有数据,1<=n<=100000, 1<=c<=10。
题解
叶子不超过 20 个。。。看成度数不超过 20 了。。。。。
于是我们可以以每个叶子为根搞出一颗 trie 树,于是得到不超过 20 颗 trie 树,然后合并这些 trie 树,在上面构造后缀自动机,然后就是裸题了。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x * f; } #define maxn 100010 #define maxm 200010 #define maxnode 2000010 #define maxNode 4000010 #define maxa 10 #define LL long long int n, m, head[maxn], nxt[maxm], To[maxm], col[maxn], ind[maxn]; void AddEdge(int a, int b) { To[++m] = b; nxt[m] = head[a]; head[a] = m; swap(a, b); To[++m] = b; nxt[m] = head[a]; head[a] = m; ind[a]++; ind[b]++; return ; } int tot, rt, ch[maxnode][maxa], fa[maxnode], fac[maxnode]; void dfs(int u, int p, int pa) { if(!ch[p][col[u]]) ch[p][col[u]] = ++tot, fa[tot] = p, fac[tot] = col[u]; for(int e = head[u]; e; e = nxt[e]) if(To[e] != pa) dfs(To[e], ch[p][col[u]], u); return ; } int Rt, ToT, to[maxNode][maxa], par[maxNode], Max[maxNode], last[maxnode]; void extend(int x, int p, int id) { int np = ++ToT; Max[np] = Max[p] + 1; last[id] = np; while(p && !to[p][x]) to[p][x] = np, p = par[p]; if(!p){ par[np] = rt; return ; } int q = to[p][x]; if(Max[q] == Max[p] + 1){ par[np] = q; return ; } int nq = ++ToT; Max[nq] = Max[p] + 1; memcpy(to[nq], to[q], sizeof(to[q])); par[nq] = par[q]; par[q] = par[np] = nq; while(p && to[p][x] == q) to[p][x] = nq, p = par[p]; return ; } int main() { n = read(); read(); for(int i = 1; i <= n; i++) col[i] = read(); for(int i = 1; i < n; i++) { int a = read(), b = read(); AddEdge(a, b); } tot = rt = 1; for(int i = 1; i <= n; i++) if(ind[i] == 1) dfs(i, rt, 0); Rt = ToT = 1; last[1] = 1; for(int i = 2; i <= tot; i++) extend(fac[i], last[fa[i]], i); // for(int i = 1; i <= ToT; i++) printf("%d(%d)%c", par[i], i, i < ToT ? ' ' : '\n'); // for(int i = 1; i <= ToT; i++) printf("%d(%d)%c", rgt[i], i, i < ToT ? ' ' : '\n'); // for(int i = 1; i <= ToT; i++) printf("%d(%d)%c", Max[i], i, i < ToT ? ' ' : '\n'); LL ans = 0; for(int i = 1; i <= ToT; i++) ans += Max[i] - Max[par[i]]; printf("%lld\n", ans); return 0; }