HNOI2019 JOJO


jojo这个坑填上了,然鹅还有序列这个题啊啊啊啊啊啊

可持久化这个东西没有强制在线就是假的,直接建树dfs就行了

这题是kmp的加强版,每次会加一堆相同的数进来

先想一个50分的傻逼暴力,因为这题和kmp一样当然往kmp方向想,设\(nxt_i\)表示第\(i\)段字符的最后一个字符的\(nxt\)。

那么有一个优化,看一下求\(nxt\)的过程,如果新加了一段\(y\)个\(x\)字符,上一个\(nxt_i\)必须满足\(A[nxt_i+1]=x\)才行,否则会跳\(nxt\),题目还给了相邻两段字符不同,那么\(A[nxt_i+1]=x\)也意味着\(A[nxt_i+1]\neq A[nxt_i]\),也即\(nxt_i\)是一段的最后一个字符,如果不是可以继续跳知道是为止

那么\(nxt\)只需要记所在的段了

再来看怎么求\(\sum\)真正的\(nxt\)。可以从假的\(nxt\)数组一直跳,并且一边跳一边皮配一段后缀。具体看代码,懒得写了。

这样复杂度是\(O(n^2)\)假的,但原题可以AC(然后被神仙卡掉)

考虑怎么把复杂度优化成真的,跳\(nxt\)时,如果字符串存在周期,那么直接跳到第一个周期。

#include<bits/stdc++.h>
#define il inline
#define rg register
#define vd void
#define mod 998244353
#define ll long long
il int gi(){
int x=0,f=0;char ch=getchar();
while(!isdigit(ch))f^=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int qop[100010],qx[100010];
std::vector<int>s[100010];
char qch[100010];
int ans[100010];
char nowch[100010];
int len,nowlen[100010],nowslen[100010],nxt[100010];
int res[100010];
il int getsum(int l,int r){return 1ll*(l+r)*(r-l+1)/2%mod;}
il vd dfs(int x){
if(qch[x])do{
++len;nowch[len]=qch[x];nowlen[len]=qx[x];nowslen[len]=nowslen[len-1]+qx[x];nxt[len]=0;res[len]=0;
if(len==1){res[len]=getsum(1,nowlen[len]-1);break;}
int p=nxt[len-1],lastgap=len-nxt[len-1];
while(p&&(nowch[p+1]!=nowch[len]||nowlen[p+1]!=nowlen[len])){
if(p-nxt[p]==lastgap)p=p%lastgap+lastgap;
lastgap=p-nxt[p],p=nxt[p];
}
if(p||(nowch[1]==nowch[len]&&nowlen[1]<=nowlen[len]))++p;
nxt[len]=p;
p=nxt[len-1];
lastgap=len-1-p;
int matchedlen=0;
while(matchedlen<nowlen[1]&&p){
if(nowch[p+1]==nowch[len]&&nowlen[p+1]>matchedlen){
res[len]=(res[len]+getsum(nowslen[p]+matchedlen+1,nowslen[p]+std::min(nowlen[p+1],nowlen[len])))%mod;
matchedlen=std::min(nowlen[len],nowlen[p+1]);
}
if(p-nxt[p]==lastgap)p=p%lastgap+lastgap;
lastgap=p-nxt[p],p=nxt[p];
}
if(matchedlen<nowlen[len]&&nowch[1]==nowch[len]){
res[len]=(res[len]+getsum(matchedlen+1,std::min(nowlen[1],nowlen[len])))%mod;
matchedlen=std::min(nowlen[len],nowlen[1]);
res[len]=(res[len]+1ll*nowlen[1]*(nowlen[len]-matchedlen))%mod;
}
res[len]=(res[len]+res[len-1])%mod;
}while(0);
ans[x]=res[len];
for(auto i:s[x])dfs(i);
if(qch[x])--len;
}
int main(){
// freopen("jojo.in","r",stdin);
// freopen("jojo.out","w",stdout);
int n=gi();
for(int i=1;i<=n;++i){
qop[i]=gi(),qx[i]=gi();
if(qop[i]==1)qch[i]=getchar();
else qch[i]=0;
if(qop[i]==1)s[i-1].push_back(i);
else s[qx[i]].push_back(i);
}
dfs(0);
for(int i=1;i<=n;++i)printf("%d\n",ans[i]);
return 0;
}

HNOI2019 JOJO的更多相关文章

  1. luogu P5287 [HNOI2019]JOJO

    传送门 神™这题暴力能A,这出题人都没造那种我考场就想到的数据,难怪我的垃圾做法有分 先考虑没有撤销操作怎么做,因为每次插入一段一样的字符,所以我们可以把\(x\)个字符\(c\)定义为\(cx\), ...

  2. 【洛谷5287】[HNOI2019] JOJO(主席树优化KMP)

    点此看题面 大致题意: 每次往一个字符串末尾加上\(x\)个字符\(c\),或者回到某一历史版本,求\(KMP\)的\(\sum Next_i\). 问题转化 考虑到可以离线. 于是,我们就可以用一个 ...

  3. [HNOI2019]JOJO(KMP自动机+主席树)

    一道神仙题,考察选手对KMP的深入理解. 先考虑没有2操作的做法.设每一段为一个二元组(x,c),考虑一段前缀匹配后缀,除了第一段的字符,其他段的二元组(x,c)必须相等,所以可以将其视为特殊字符进行 ...

  4. ZJOI2019Day2余姚中学游记(4.23~4.26)

    前言 \(Day2\),又是一场噩梦. 前段时间去做了挺多十二省联考和\(HNOI2019\)的题目,还订正掉了\(Day1\)的\(T1\)和\(T2\)(\(T3\)动态\(DP\)完全不想订正啊 ...

  5. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

  6. 【loj - 3055】「HNOI2019」JOJO

    目录 description solution accepted code details description JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或 ...

  7. LOJ 3055 「HNOI2019」JOJO—— kmp自动机+主席树

    题目:https://loj.ac/problem/3055 先写了暴力.本来想的是 n<=300 的那个在树上暴力维护好整个字符串, x=1 的那个用主席树维护好字符串和 nxt 数组.但 x ...

  8. HNOI2019游记

    \(day~?\) 我们的老师告诉我说,你这次省选目标分:\(70\),拿不到,家法伺候.但其实,我的目标是不爆零!!! \(day~-1\) 这天晚上,我们的指导老师给我们试了一下ZJOI2019, ...

  9. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

随机推荐

  1. MYSQL获取当前年、季、月、周第一天、最后一天的日期/时间戳

    因为做一些商场某个会员今年的消费分析,所以对sql中时间的获取进行了判断. 例如获取今年(即当前年的第一天到昨天0时之间)的消费总额. 如果需要时间戳转换,用UNIX_TIMESTAMP()函数. 一 ...

  2. 洗礼灵魂,修炼python(29)--装饰器(1)—>利用经典案例解析装饰器概念

    前提必备 不急着进入正题,在前面函数作用域那一章介绍了闭包,全局变量局部变量,这里再看几个简单的闭包案例: 1):不带参数 注意: 1.这里的name属性是每个函数都有的,可以反馈函数名 2.temp ...

  3. Node.js中文乱码解决方法

  4. [SequenceFile_2] SequenceFile 的基本操作

    0. 说明 测试序列文件的读写操作 && 测试序列文件的排序操作 && 测试序列文件的合并操作 && 测试序列文件的压缩方式 && 测试 ...

  5. React路由 + 绝对路径引用

    路由: 哈希路由(在url地址后加   #name) // 实现页面监听 window.onhashchange = function(){ console.log(‘hash:’,window.lo ...

  6. 在Markdown中转载CSDN博客

    1.CSDN博客页面右键,点击[检查] 点击检查后,页面右侧出现html代码,如下图 2.如果需要转载全文,则在html代码下侧点击选中article_content 即可,会在代码框中自动选中art ...

  7. C# 接受MQTT服务器推送的消息

    前言: MQTT是IBM开发的一个即时通讯协议.MQTT是面向M2M和物联网的连接协议,采用轻量级发布和订阅消息传输机制. 大家可以直接上GitHub下载MQQT服务的源码,源码地址:https:// ...

  8. Android——Intent和Intent过滤器

    http://www.cnblogs.com/XP-Lee/p/3613830.html Intent就是一个激活组件的消息对象,用于组件之间的通信.需要注意的是,能被Intent激活通信的组件只有三 ...

  9. [HAOI2017]供给侧改革

    题目 这道题我们其实就是利用了一棵后缀树 由于字符串是随机的,所以这个后缀树的树高是\(log\)的,基于树高的算法是能过的 我们考虑后缀树上的两个节点的\(lca\)就是这两个节点所代表的后缀的\( ...

  10. P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib (数论—素数 + DFS)

    这大概是我写的第一个DFS 题目描述 农民约翰的母牛总是产生最好的肋骨.你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们.农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨, ...