#trie,树链剖分#洛谷 6088 [JSOI2015]字符串树
分析
显然树上的问题可以转换成根节点到两点的答案减去2倍根节点到LCA的答案
化边为点,考虑子节点承接父节点的trie,再加入一条新的字符串,
在循环的过程中统计一个位置被多少个字符串经过,
这样在查询的时候直接访问某个trie跳到末尾找到答案
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=100101; char s[N][11];
struct node{int y,next;}e[N<<1];
int Len[N],trie[N*10][26],sum[N*10],n,k=1,dep[N];
int dfn[N],son[N],top[N],fat[N],as[N],rt[N],Tot,tot,big[N];
inline signed iut(){
rr signed ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed Insert(int Rt,int j){
rr int trt=++Tot;
for (rr int i=1;i<=Len[j];++i){
for (rr int p=0;p<26;++p)
trie[Tot][p]=trie[Rt][p];
sum[Tot]=sum[Rt]+1;
trie[Tot][s[j][i]-97]=Tot+1,
Rt=trie[Rt][s[j][i]-97],++Tot;
}
sum[Tot]=sum[Rt]+1;
for (rr int p=0;p<26;++p)
trie[Tot][p]=trie[Rt][p];
return trt;
}
inline signed query(int Rt){
for (rr int j=1;j<=Len[0];++j)
Rt=trie[Rt][s[0][j]-97];
return sum[Rt];
}
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
for (rr int i=as[x],mson=-1;i;i=e[i].next)
if (e[i].y!=fa){
rt[e[i].y]=Insert(rt[x],i>>1);
dfs1(e[i].y,x),son[x]+=son[e[i].y];
if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
}
}
inline void dfs2(int x,int linp){
dfn[x]=++tot,top[x]=linp;
if (!big[x]) return; dfs2(big[x],linp);
for (rr int i=as[x];i;i=e[i].next)
if (e[i].y!=fat[x]&&e[i].y!=big[x])
dfs2(e[i].y,e[i].y);
}
inline signed Lca(int x,int y){
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
x=fat[top[x]];
}
if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
return x;
}
signed main(){
n=iut();
for (rr int i=1;i<n;++i){
rr int x=iut(),y=iut();
e[++k]=(node){y,as[x]},as[x]=k;
e[++k]=(node){x,as[y]},as[y]=k;
rr char c=getchar();
while (!isalpha(c)) c=getchar();
while (isalpha(c)) s[i][++Len[i]]=c,c=getchar();
}
dfs1(1,0),dfs2(1,1);
for (rr int Q=iut();Q;--Q,putchar(10)){
rr int x=iut(),y=iut(),lca=Lca(x,y);
rr char c=getchar(); Len[0]=0;
while (!isalpha(c)) c=getchar();
while (isalpha(c)) s[0][++Len[0]]=c,c=getchar();
print(query(rt[x])+query(rt[y])-2*query(rt[lca]));
}
return 0;
}
#trie,树链剖分#洛谷 6088 [JSOI2015]字符串树的更多相关文章
- AC日记——【模板】树链剖分 洛谷 P3384
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- 树链剖分 - Luogu 3384【模板】树链剖分
[模板]树链剖分 题目描述 已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操 ...
- 树剖+线段树||树链剖分||BZOJ1984||Luogu4315||月下“毛景树”
题面:月下“毛景树” 题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好).用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了:前三个更新的操作都可以合并起来,可以发现a到b节点间 ...
- poj 3237 树链剖分模板(用到线段树lazy操作)
/* 本体在spoj375的基础上加了一些操作,用到线段树的lazy操作模板类型 */ #include<stdio.h> #include<string.h> #includ ...
- 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...
- 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点
题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...
- 【模板时间】◆模板·II◆ 树链剖分
[模板·II]树链剖分 学长给我讲树链剖分,然而我并没有听懂,还是自学有用……另外感谢一篇Blog +by 自为风月马前卒+ 一.算法简述 树链剖分可以将一棵普通的多叉树转为线段树计算,不但可以实现对 ...
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
- HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
随机推荐
- 在Mac下使用zsh
什么是zsh 简单来说,zsh是一个构建于bash之上的shell工具,详见:zsh . 相比起bash,zsh默认支持许多非常实用的功能,比如:可以显示当前所在的git分支,这对于程序员来说是非常有 ...
- Taurus.MVC WebMVC 入门开发教程2:一个简单的页面呈现
前言: 在上一篇中,我们了解了如何下载.配置和运行 Taurus.MVC WebMVC 框架. 现在,让我们开始编写一个简单的页面并进行呈现. 步骤1:创建控制器 首先,我们需要创建一个控制器来处理页 ...
- 硬件开发笔记(五): 硬件开发基本流程,制作一个USB转RS232的模块(四):创建CON连接器件封装并关联原理图元器件
前言 有了原理图,可以设计硬件PCB,在设计PCB之间还有一个协同优先动作,就是映射封装,原理图库的元器件我们是自己设计的.为了更好的表述封装设计过程,本文描述了一个创建CON标准连接件封装,创建 ...
- 协程与yield表达式
在函数内,yield语句可以作为表达式使用,出现在赋值运算符的右边,例如: def receiver(): print("Ready to receive") while True ...
- 【会员题】253. 会议室 II
会议室II 给定一个会议时间安排的数组,每个会议时间都会包括开始和结束的时间s1,e1,s2,e2]..](si<ei) ,为避免会议冲突,同时要考虑充分 利用会议室资源,请你计算至少需要多少间 ...
- 【Azure 事件中心】通过 az rest --method get 如何获得Event Hub Entity 级的统计指标
问题描述 通过 az rest --method get 如何获得Event Hub Entity 级的统计指标? 问题解答 查阅文档 https://learn.microsoft.com/en ...
- 【Azure 事件中心】Flink消费Event Hub中事件, 使用Azure默认示例代码,始终获取新产生的事件,如何消费旧事件呢?
问题描述 根据Azure Event Hub示例文档,[将 Apache Flink 与适用于 Apache Kafka 的 Azure 事件中心配合使用],配置好 consumer.config 文 ...
- 协程的async使用
async与launch一样都是开启一个协程,但是async会返回一个Deferred对象,该Deferred也是一个job async函数类似于 launch函数.它启动了一个单独的协程,这是一个轻 ...
- 使用C#创建服务端Web API
前言 C# Web API 是一种基于 .NET 平台(包括但不限于.NET Framework 和 .NET Core)构建 HTTP 服务的框架,用于创建 RESTful Web 服务.REST( ...
- RCC & GPIO库函数&传感器输入
RCC: Reset and Clock Control,即复位和时钟控制. 一般在.h文件的末尾都是一些函数声明,RCC常用的三个函数(外设时钟控制,没有时钟外设不工作): void RCC_A ...