zoukankan      html  css  js  c++  java
  • [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
    ",ans[pos[i]]);
      return 0;
    }
    
  • 相关阅读:
    QTableWidget的使用和美工总结
    pyqt下QTableWidget使用方法小结(转)
    改变QTableWidget 行高(转)
    Qt中 文件对话框QFileDialog 的使用
    Qt:拖拽图片到QLabel上并显示(转)
    Qt获取组合键(转)
    Qt图片显示效率的比较(转)
    QComboBox用法小列(转)
    TinyXML:一个优秀的C++ XML解析器(转)
    JZOJ 3099. Vigenère密码 NOIP2012
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10940485.html
Copyright © 2011-2022 走看看