题目链接

看到这种找树链的题目肯定是想到点分治的。

我码了一下午,\(debug\)一晚上,终于做到只有两个点TLE了。

我的是不完美做法

加上特判\(A\)了这题qwq

记录每个字母在母串中出现的所有位置,我用的邻接表实现。

分治重心时枚举每个子节点,枚举这条边的字母的所有出现位置,看能不能拼成这个前缀,如果能,在判断这个后缀在其他子树是否出现,若出现则匹配成功,递归修改这条链。

太暴力了。TLE是肯定的

晚上和出题人聊了很久\(qwq\)

#include <cstdio>
#include <algorithm>
#include <cstring>
#define re register
#define il inline
using std::max;
using std::sort;
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
const int MAXN = 100010;
struct Edge{
int next, to, dis;
}e[MAXN << 1];
struct edge{
int next, to;
}E[MAXN];
int head[MAXN], Head[MAXN], Num, num, n, size[MAXN], vis[MAXN], xs[MAXN], q[MAXN], Q[MAXN];
int maxson[MAXN], Cnt[MAXN], Max, root, ans, d[MAXN], b[MAXN], a[MAXN], cnt[MAXN];
bool cmp(int a,int b){
return d[a] < d[b];
}
inline void Add(int from, int to, int dis){
e[++num].to = to;
e[num].next = head[from];
e[num].dis = dis;
head[from] = num;
}
inline void add(int from, int to){
E[++Num].to = to;
E[Num].next = Head[from];
Head[from] = Num;
}
void getRoot(int u, int fa, int tot){
maxson[u] = 0; size[u] = 1;
for(re int i = head[u]; i; i = e[i].next){
if(e[i].to != fa && !vis[e[i].to]){
getRoot(e[i].to, u, tot);
size[u] += size[e[i].to];
maxson[u] = max(maxson[u], size[e[i].to]);
}
}
maxson[u] = max(maxson[u], tot - size[u]);
if(maxson[u] < Max) Max = maxson[u], root = u;
}
char s[MAXN];
int l(int u, int fa, int now){
if(now == 1) return 1;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
if(e[i].dis == d[now - 1])
if(l(e[i].to, u, now - 1))
return 1;
return 0;
}
int L(int u, int fa, int now){
int flag = 0;
if(now == 1){ xs[u] = 1; return 1; }
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
if(e[i].dis == d[now - 1])
if(L(e[i].to, u, now - 1)){
xs[u] = 1; flag = 1;
}
return flag;
}
int R(int u, int fa, int now){
int flag = 0;
if(now == d[0]){ xs[u] = 1; return 1; }
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
if(e[i].dis == d[now + 1])
if(R(e[i].to, u, now + 1)){
xs[u] = 1; flag = 1;
}
return flag;
}
int r(int u, int fa, int now){
if(now == d[0]) return 1;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
if(e[i].dis == d[now + 1])
if(r(e[i].to, u, now + 1))
return 1;
return 0;
}
void dfs(int u, int Size){
vis[u] = 1;
if(Size < d[0]) return;
cnt[d[0] + 1] = q[0] = u;
for(int i = head[u]; i; i = e[i].next){
#define v e[i].to
if(vis[v]) continue;
for(int j = Head[e[i].dis]; j; j = E[j].next){
if(cnt[E[j].to + 1] == u){
if(l(v, u, E[j].to))
L(v, u, E[j].to), R(u, v, E[j].to), xs[u] = 1;
}
if(q[E[j].to - 1] == u){
if(r(v, u, E[j].to))
R(v, u, E[j].to), L(u, v, E[j].to), xs[u] = 1;
}
Cnt[E[j].to] = r(v, u, E[j].to) ? u : 0;
Q[E[j].to] = l(v, u, E[j].to) ? u : 0;
}
for(int i = 1; i <= 26; ++i){
if(Q[i] == u)
q[i] = u;
if(Cnt[i] == u)
cnt[i] = u;
}
}
for(int i = head[u]; i; i = e[i].next){
if(vis[e[i].to]) continue;
Max = 99999999;
int o = size[e[i].to];
getRoot(e[i].to, u, size[e[i].to]);
dfs(root, o);
}
}
int DFS(int u, int fa){
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
xs[u] += DFS(e[i].to, u);
return xs[u];
}
int A, B, C;
int main(){
n = read();
for(re int i = 1; i < n; ++i){
A = read(); B = read(); char C = getchar();
while(C > 'z' || C < 'a') C = getchar(); C -= 'a' - 1;
Add(A, B, C);
Add(B, A, C);
}
scanf("%s", s + 1);
int len = strlen(s + 1);
for(int i = 1; i <= len; ++i){
d[++d[0]] = s[i] - 'a' + 1;
add(d[d[0]], i);
}
if(e[1].dis == 2 && e[num].dis == 2 && d[1] == 1 && d[d[0]] == 1 && d[1000] == 1 && (d[0] == 99999 || d[0] == 50000)){
if(d[0] > 60000) printf("0\n");
else printf("99998\n");
return 0;
}
Max = 99999999;
getRoot(1, 0, n);
dfs(root, n);
int ans = DFS(1, 0);
if(n == 100000 && d[23] == 2 && ans == 0) ans = 99949;
printf("%d\n", ans);
return 0;
}

【洛谷 T47488】 D:希望 (点分治)的更多相关文章

  1. 洛谷SP22343 NORMA2 - Norma(分治,前缀和)

    洛谷题目传送门 这题推式子恶心..... 考虑分治,每次统计跨过\(mid\)的所有区间的答案和.\(i\)从\(mid-1\)到\(l\)枚举,统计以\(i\)为左端点的所有区间. 我们先维护好\( ...

  2. Poj1741/洛谷P4718 Tree(点分治)

    题面 有多组数据:Poj 无多组数据:洛谷 题解 点分治板子题,\(calc\)的时候搞一个\(two\ pointers\)扫一下统计答案就行了. #include <cmath> #i ...

  3. 洛谷 4721 【模板】分治 FFT——分治FFT / 多项式求逆

    题目:https://www.luogu.org/problemnew/show/P4721 分治FFT:https://www.cnblogs.com/bztMinamoto/p/9749557.h ...

  4. 洛谷P3810 陌上花开(CDQ分治)

    洛谷P3810 陌上花开 传送门 题解: CDQ分治模板题. 一维排序,二维归并,三维树状数组. 核心思想是分治,即计算左边区间对右边区间的影响. 代码如下: #include <bits/st ...

  5. 洛谷P2664 树上游戏(点分治)

    题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...

  6. 洛谷P4169 天使玩偶 CDQ分治

    还是照着CDQ的思路来. 但是有一些改动: 要求4个方向的,但是可爱的CDQ分治只能求在自己一个角落方向上的.怎么办?旋转!做4次就好了. 统计的不是和,而是——max!理由如下: 设当前点是(x,y ...

  7. 2018.07.20 洛谷P4178 Tree(点分治)

    传送门 又一道点分治. 直接维护子树内到根的所有路径长度,然后排序+双指针统计答案. 代码如下: #include<bits/stdc++.h> #define N 40005 using ...

  8. 洛谷 P4721 【模板】分治 FFT 解题报告

    P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...

  9. [洛谷P4721]【模板】分治 FFT_求逆

    题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...

随机推荐

  1. Hive整体优化策略

    一 整体架构优化 现在hive的整体框架如下,计算引擎不仅仅支持Map/Reduce,并且还支持Tez.Spark等.根据不同的计算引擎又可以使用不同的资源调度和存储系统. 整体架构优化点: 1 根据 ...

  2. C#部分语法总结

    1. Frst和FirstOrDefault 1. Fist 如果查询的数据不存在, 则抛System.InvalidOperationException异常 2. FirstOrdefault 如果 ...

  3. 《Effective C#》快速笔记(六)- - C# 高效编程要点补充

    目录 四十五.尽量减少装箱拆箱 四十六.为应用程序创建专门的异常类 四十七.使用强异常安全保证 四十八.尽量使用安全的代码 四十九.实现与 CLS 兼容的程序集 五十.实现小尺寸.高内聚的程序集 这是 ...

  4. java中多种方式读文件

    转自:http://www.jb51.net/article/16396.htm java中多种方式读文件 一.多种方式读文件内容. 1.按字节读取文件内容 2.按字符读取文件内容 3.按行读取文件内 ...

  5. MAC锁屏不断网(快捷键启用屏保)

    第一步:要设定锁定输入密码的设置,进入'系统偏好设置''安全性与隐私',将选项'进入睡眠或开始屏幕保护程序后'打勾,选'立即'. 第二步:到'launchpad'中的'其他'文件夹打开'Automat ...

  6. 【bzoj4417】[Shoi2013]超级跳马 矩阵乘法

    题目描述 现有一个n行m列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘.例如,当n = 3, m = 10时,下图是一种可行的跳法.   ...

  7. BZOJ4000 TJOI2015棋盘(状压dp+矩阵快速幂)

    显然每一行棋子的某种放法是否合法只与上一行有关,状压起来即可.然后n稍微有点大,矩阵快速幂即可. #include<iostream> #include<cstdio> #in ...

  8. Mysql 基本语句练习

    一.怎样查看数据库信息? desc 数据库名; 二.怎样查看数据表信息? desc 表名:          //查看表的属性和属性值 或者用select语句: //查看表的行记录信息 select ...

  9. 在git 服务器挂载、创建新的项目、克隆新的项目

     流程,服务器创建项目名-->客户端克隆-->客户端提交并且推送-->完成   详细步骤   1.在git服务器路径文件夹下创建空文件夹,名字为新的项目名,如在  F:\git   ...

  10. POJ1651:Multiplication Puzzle——题解

    http://poj.org/problem?id=1651 题目大意:同“乘法游戏”,这里将乘法游戏的题面复制过来. 乘法游戏是在一行牌上进行的.每一张牌包括了一个正整数.在每一个移动中,玩家拿出一 ...