【洛谷 T47488】 D:希望 (点分治)
题目链接
看到这种找树链的题目肯定是想到点分治的。
我码了一下午,\(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:希望 (点分治)的更多相关文章
- 洛谷SP22343 NORMA2 - Norma(分治,前缀和)
洛谷题目传送门 这题推式子恶心..... 考虑分治,每次统计跨过\(mid\)的所有区间的答案和.\(i\)从\(mid-1\)到\(l\)枚举,统计以\(i\)为左端点的所有区间. 我们先维护好\( ...
- Poj1741/洛谷P4718 Tree(点分治)
题面 有多组数据:Poj 无多组数据:洛谷 题解 点分治板子题,\(calc\)的时候搞一个\(two\ pointers\)扫一下统计答案就行了. #include <cmath> #i ...
- 洛谷 4721 【模板】分治 FFT——分治FFT / 多项式求逆
题目:https://www.luogu.org/problemnew/show/P4721 分治FFT:https://www.cnblogs.com/bztMinamoto/p/9749557.h ...
- 洛谷P3810 陌上花开(CDQ分治)
洛谷P3810 陌上花开 传送门 题解: CDQ分治模板题. 一维排序,二维归并,三维树状数组. 核心思想是分治,即计算左边区间对右边区间的影响. 代码如下: #include <bits/st ...
- 洛谷P2664 树上游戏(点分治)
题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...
- 洛谷P4169 天使玩偶 CDQ分治
还是照着CDQ的思路来. 但是有一些改动: 要求4个方向的,但是可爱的CDQ分治只能求在自己一个角落方向上的.怎么办?旋转!做4次就好了. 统计的不是和,而是——max!理由如下: 设当前点是(x,y ...
- 2018.07.20 洛谷P4178 Tree(点分治)
传送门 又一道点分治. 直接维护子树内到根的所有路径长度,然后排序+双指针统计答案. 代码如下: #include<bits/stdc++.h> #define N 40005 using ...
- 洛谷 P4721 【模板】分治 FFT 解题报告
P4721 [模板]分治 FFT 题目背景 也可用多项式求逆解决. 题目描述 给定长度为 \(n−1\) 的数组 \(g[1],g[2],\dots,g[n-1]\),求 \(f[0],f[1],\d ...
- [洛谷P4721]【模板】分治 FFT_求逆
题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:分治$FFT$博客,发现 ...
随机推荐
- Winform 子窗体设置刷新父窗体
方法1:所有权法 父窗体:Form1 子窗体:Form2 //Form1:窗体代码 //需要有一个公共的刷新方法 public void Refresh_Method() { //... } / ...
- Oracle AWR日志使用
SQL>@?/rdbms/admin/awrrpt.sql Specify the Report Type ~~~~~~~~~~~~~~~~~~~~~~~ Would you like an H ...
- 深入理解java内置锁(synchronized)和显式锁(ReentrantLock)
多线程编程中,当代码需要同步时我们会用到锁.Java为我们提供了内置锁(synchronized)和显式锁(ReentrantLock)两种同步方式.显式锁是JDK1.5引入的,这两种锁有什么异同呢? ...
- apiDoc 入门
网站 http://apidocjs.com/#demo Install npm install apidoc -g Run apidoc -i myapp/ -o apidoc/ -t mytemp ...
- BZOJ 3507 通配符匹配(贪心+hash或贪心+AC自动机)
首先可以对n个目标串单独进行处理. 对于每个目标串,考虑把模式串按'*'进行划分为cnt段.首尾两段一定得于原串进行匹配.剩下的cnt-2段尽量与最靠左的起点进行匹配. 对于剩下的cnt-2段.每段又 ...
- BZOJ 1196 公路修建问题(二分+最小生成树)
题目要求求出图中的一颗生成树,使得最大的边权最小,且满足一级公路的个数>=k. 考虑二分最大边,问题就变为给出的图的生成树中,是否满足所有的边<=val,且一级公路的个数>=k. 所 ...
- Linux特殊字符含义
文件名以 ' . ' 开头的都是隐藏文件或目录,只需要在文件或目录名前添加 ' . ' 就可以隐藏它 ~ 表示主目录 . 当前目录 . . ...
- URL 编码规则
规则: 1.将空格转换为加号(+) 2.对0-9.a-z.A-Z之间的字符保持不变 3.对于所有其他的字符,用这个字符的当前当前字符集编码在内存中的十六进制格式表示,并在每一个字节前加上一个百分号(% ...
- [USACO06NOV]玉米田Corn Fields 状压DP
题面: 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地.John打算在牧场上的某几格里种上美味的草,供他的 ...
- BZOJ3832 [Poi2014]Rally 【拓扑序 + 堆】
题目链接 BZOJ3832 题解 神思路orz,根本不会做 设\(f[i]\)为到\(i\)的最长路,\(g[i]\)为\(i\)出发的最长路,二者可以拓扑序后\(dp\)求得 那么一条边\((u,v ...