[HNOI2019]JOJO(KMP自动机+主席树)
一道神仙题,考察选手对KMP的深入理解。
先考虑没有2操作的做法。设每一段为一个二元组(x,c),考虑一段前缀匹配后缀,除了第一段的字符,其他段的二元组(x,c)必须相等,所以可以将其视为特殊字符进行匹配。在串末尾加入(x,c)时,显然不断跳next数组,如果当前前缀后接的字符为c ,那么可以增加一段首项为当前前缀长度,然后发现这一段的next数组为首项为前缀长度,公差为1的等差数列。next链上如果有等于(x,c)的二元组,则next指向二元组,否则指向0,因为如果存在(y,c)满足y>x,则一定无法匹配。
解决了没有2操作的做法,考虑有2操作,由于KMP复杂度是均摊的,很显然不能直接在树上dfs,所以要优化求next过程。考虑离线建树,dfs时维护每条next链上的KMP自动机,f[i][j][k]表示状态i下加入二元组(j,k)next指向哪,g[i][j][k]表示产生的贡献,每次修改复制前一次的f数组,修改f[i][x][c],g[i][x][1...c]为等差数列,此处可以用主席树实现。
#include<bits/stdc++.h>
#define lson l,mid,tr[rt].lc
#define rson mid+1,r,tr[rt].rc
using namespace std;
const int N=1e5+,M=1e4+,mod=;
struct node{int lc,rc,sum,lazy,nxt;}tr[N*];
int n,tot,top,val[N],pos[N],ans[N],a[N],b[N],rt[N][],mx[N][];
vector<int>G[N];
void newnode(int&x){tr[++tot]=tr[x],x=tot;}
void add(int x,int v,int len){tr[x].sum=1ll*v*len%mod,tr[x].lazy=v;}
int S(int x){return 1ll*x*(x+)/%mod;}
void pushdown(int l,int r,int rt)
{
if(!tr[rt].lazy)return;
int mid=l+r>>;
newnode(tr[rt].lc),add(tr[rt].lc,tr[rt].lazy,mid-l+);
newnode(tr[rt].rc),add(tr[rt].rc,tr[rt].lazy,r-mid);
tr[rt].lazy=;
}
void update(int k,int v,int p,int l,int r,int&rt)
{
newnode(rt);
if(r<k){add(rt,v,r-l+);return;}
if(l==r){tr[rt].nxt=p,add(rt,v,);return;}
pushdown(l,r,rt);
int mid=l+r>>;
update(k,v,p,lson);
if(k>mid)update(k,v,p,rson);
tr[rt].sum=(tr[tr[rt].lc].sum+tr[tr[rt].rc].sum)%mod;
}
void query(int k,int&ans,int&nxt,int l,int r,int&rt)
{
if(r<k){ans=(ans+tr[rt].sum)%mod;return;}
if(l==r){ans=(ans+tr[rt].sum)%mod,nxt=tr[rt].nxt;return;}
pushdown(l,r,rt);
int mid=l+r>>;
query(k,ans,nxt,lson);
if(k>mid)query(k,ans,nxt,rson);
}
void dfs(int u)
{
++top;
int x=val[u]/M,y=val[u]%M,nxt=;
a[top]=val[u],b[top]=b[top-]+y;
if(top==)ans[u]=S(y-);
else{
ans[u]=(ans[u]+S(min(mx[top][x],y)))%mod;
query(y,ans[u],nxt,,M,rt[top][x]);
if(!nxt&&a[]/M==x&&b[]<y)nxt=,ans[u]=(ans[u]+1ll*b[]*max(,y-mx[top][x]))%mod;
}
mx[top][x]=max(mx[top][x],y);
update(y,b[top-],top,,M,rt[top][x]);
for(int i=;i<G[u].size();i++)
{
memcpy(mx[top+],mx[nxt+],sizeof mx[top+]);
memcpy(rt[top+],rt[nxt+],sizeof rt[top+]);
ans[G[u][i]]=ans[u],dfs(G[u][i]);
}
--top;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==)
{
char c;cin>>c;
val[++tot]=(c-'a')*M+x,pos[i]=tot,G[pos[i-]].push_back(pos[i]);
}
else pos[i]=pos[x];
}
for(int i=;i<G[].size();i++)
{
tot=;
memset(rt[],,sizeof rt[]);
memset(mx[],,sizeof mx[]);
dfs(G[][i]);
}
for(int i=;i<=n;i++)printf("%d\n",ans[pos[i]]);
}
[HNOI2019]JOJO(KMP自动机+主席树)的更多相关文章
- LOJ 3055 「HNOI2019」JOJO—— kmp自动机+主席树
题目:https://loj.ac/problem/3055 先写了暴力.本来想的是 n<=300 的那个在树上暴力维护好整个字符串, x=1 的那个用主席树维护好字符串和 nxt 数组.但 x ...
- NOI 2011 阿狸的打字机(AC自动机+主席树)
题意 https://loj.ac/problem/2444 思路 多串匹配,考虑 \(\text{AC}\) 自动机.模拟打字的过程,先建出一棵 \(\text{Trie}\) 树,把它变成自动机 ...
- Bzoj2534:后缀自动机 主席树启发式合并
国际惯例的题面:考虑我们求解出字符串uvu第一个u的右端点为i,第二个u的右端点为j,我们需要满足什么性质?显然j>i+L,因为我们选择的串不能是空串.另外考虑i和j的最长公共前缀(也就是说其p ...
- luogu P5826 【模板】子序列自动机 主席树 vector 二分
LINK:子序列自动机 想了一些很有趣的做法. dp 容易看出 f[i][j]表示前i个数匹配了j个数的dp 不过复杂度很高. 贪心 容易想到匹配的时候每个数字尽量往前匹配 这样显然是最优的 复杂度Q ...
- CodeForces 547E Mike and Friends AC自动机 主席树
题意: 给出\(n\)个字符串\(s_i\)和\(q\)个询问: \(l,r,k\):\(\sum\limits_{i=l}^{r}count(i, k)\),其中\(count(i,j)\)表示\( ...
- 【洛谷5287】[HNOI2019] JOJO(主席树优化KMP)
点此看题面 大致题意: 每次往一个字符串末尾加上\(x\)个字符\(c\),或者回到某一历史版本,求\(KMP\)的\(\sum Next_i\). 问题转化 考虑到可以离线. 于是,我们就可以用一个 ...
- 【BZOJ-4556】字符串 后缀数组+二分+主席树 / 后缀自动机+线段树合并+二分
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 657 Solved: 274[Su ...
- CodeForces 547E:Mike and Friends(AC自动机+DFS序+主席树)
What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...
- CF547E Milk and Friends(AC自动机的fail指针上建主席树 或 广义后缀自动机的parent线段树合并)
What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...
随机推荐
- NET CLR via C#(第4版)第4章 类型基础
本章内容: 1 所有类型都从System.Object派生 2 类型转换 3 命名空间和程序集 4 运行时的相互关系 本章讲述使用类型和CLR时需掌握的基础知识.具体地说,要讨论所有类型都具有的一 ...
- zookeeper基础教程
一.关于zookeeper Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储, Zookeeper 作用 ...
- DRF项目之JWT认证方式的简介及使用
什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...
- python3.4+Django+pymysql
pip install Pymysql 修改app里面的__init__.py import pymysqlpymysql.install_as_MySQLdb()
- Cracking Digital VLSI Verification Interview 第一章
目录 Digital Logic Design Number Systems, Arithmetic and Codes Basic Gates Combinational Logic Circuit ...
- Python pip安装时You are using pip version 9.0.1, however version 18.0 is available. You should consider upgrading via the 'python -m pip install --upgrade pip' command.
在我们安装第三方库的时候会在结尾出现如下两行内容 You are using pip version 9.0.1, however version 18.0 is available. You sho ...
- C# 创建Windows服务。服务功能:定时操作数据库
一.创建window服务 1.新建项目-->选择Windows服务.默认生成文件包括Program.cs,Service1.cs 2.在Service1.cs添加如下代码: System.T ...
- win10使用笔记本自带显卡GUP安装CUDA,版本问题
1.GPU算力问题 查询:win+r, GPU:GeForce GTX 850m,算力5.0,还可以跑得起来深度项目 2.我们需要查看NVIDIA驱动版本,才能安装合适的CUDA版本. 在C:\Pro ...
- java RSA 加密解密
package com.rsa; import java.security.KeyFactory; import java.security.KeyPair; import java.security ...
- 机器学习分布式框架horovod安装 (Linux环境)
1.openmi 下载安装 下载连接: https://download.open-mpi.org/release/open-mpi/v4.0/openmpi-4.0.1.tar.gz 安装命令 1 ...