[HNOI2019]JOJO
作者:互联网
https://www.luogu.org/problemnew/show/P5287
题解
可持久化\(KMP\)。
那个退回操作我们可以把它看做在操作树上\(dfs\),所以我们可以先把这个树弄出来。
对于连续一段串的匹配问题。
我们可以搞个\(KMP\)自动机,输入当前节点编号也就是\(nxt\),输入下一段连续的字符串,输出\(nxt\)跳完之后的值。
然后我们可以把这个字符串的\(fail\)树弄出来,然后把它搞成一个主席树,相当于是我们令\(ch[now][c][len]\)为这个自动机,第三维比较大,用线段树维护,然后\(dfs\)这颗操作树的时候顺便维护这个节点的\(nxt\),这个点的主席树从fail节点继承。
还要维护从这个点到\(fail\)树根的一条链上\(x\)字符的最长长度,还要在线段树上维护匹配时产生的贡献。
注意特判一些情况比如说开头结尾的字符时一样的。
代码
#include<bits/stdc++.h>
#define mm make_pair
#define P pair<int,int>
#define ls tr[cnt].l
#define rs tr[cnt].r
#define N 100009
using namespace std;
typedef long long ll;
const int M=10001;
vector<int>vec[N];
const int mod=998244353;
int tot,head[N],rt[N][26],mx[N][26],pos[N],tag,top,n,tott,len[N];
P rec[N];
ll ans[N];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
struct node{
int l,r,nxt;
ll sum,la;
}tr[N*30];
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
inline int newnode(int pre){
++tott;
tr[tott]=tr[pre];
return tott;
}
inline void pushdown(int cnt,int l1,int l2){
ls=newnode(ls);
MOD(tr[ls].sum=l1*tr[cnt].la%mod);
rs=newnode(rs);
MOD(tr[rs].sum=l2*tr[cnt].la%mod);
tr[ls].la=tr[rs].la=tr[cnt].la;
tr[cnt].la=0;
}
void query(int cnt,int l,int r,int R,ll &ans,int &nxt){
if(r<R){
MOD(ans+=tr[cnt].sum);
return;
}
if(l==r){
MOD(ans+=tr[cnt].sum);
nxt=tr[cnt].nxt;
return;
}
int mid=(l+r)>>1;
if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
query(ls,l,mid,R,ans,nxt);
if(mid<R)query(rs,mid+1,r,R,ans,nxt);
}
void upd(int &cnt,int l,int r,int R,int x,int nxt){
cnt=newnode(cnt);
if(r<R){
MOD(tr[cnt].sum=1ll*(r-l+1)*x%mod);
MOD(tr[cnt].la=x);
return;
}
if(l==r){
MOD(tr[cnt].sum=1ll*(r-l+1)*x%mod);
tr[cnt].nxt=nxt;
return;
}
int mid=(l+r)>>1;
if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
upd(ls,l,mid,R,x,nxt);
if(mid<R)upd(rs,mid+1,r,R,x,nxt);
MOD(tr[cnt].sum=tr[ls].sum+tr[rs].sum);
}
inline ll calc(ll x){return ((x*(x+1))/2)%mod;}
void dfs(int u){
++top;
int x=rec[u].first,y=rec[u].second;
if(top==1)tag=x;
int nxt=0;
len[top]=len[top-1]+y;
if(top==1){ans[u]=calc(y-1);}
else{
MOD(ans[u]+=calc(min(mx[top][x],y)));
query(rt[top][x],1,M,y,ans[u],nxt);
if(!nxt&&tag==x&&len[1]<y){
nxt=1;
(ans[u]+=len[1]*max(0,y-mx[top][x]))%=mod;
}
}
mx[top][x]=max(mx[top][x],y);
upd(rt[top][x],1,M,y,len[top-1],top);
for(vector<int>::iterator it=vec[u].begin();it!=vec[u].end();++it){
int v=*it;
ans[v]=ans[u];
memcpy(mx[top+1],mx[nxt+1],sizeof(mx[top+1]));
memcpy(rt[top+1],rt[nxt+1],sizeof(rt[top+1]));
dfs(v);
}
--top;
}
int main(){
n=rd();
int opt,x;
for(int i=1;i<=n;++i){
opt=rd();x=rd();
if(opt==1){
char c;
cin>>c;
rec[++tot]=mm(c-'a',x);
pos[i]=tot;
vec[pos[i-1]].push_back(pos[i]);
}
else{
pos[i]=pos[x];
}
}
for(vector<int>::iterator it=vec[0].begin();it!=vec[0].end();++it){
int v=*it;
tott=0;
memset(rt[1],0,sizeof(rt[1]));
memset(mx[1],0,sizeof(mx[1]));
dfs(v);
}
for(int i=1;i<=n;++i)printf("%d\n",ans[pos[i]]);
return 0;
}
标签:JOJO,nxt,cnt,int,tr,mid,ls,HNOI2019 来源: https://www.cnblogs.com/ZH-comld/p/10940485.html