• [SDOI2016]生成魔咒


    渐渐感觉到省选难度的天差地别

    题解:

    前60是送给暴力的?

    后面40分

    首先其子串个数就不是能统计范围内的,所以hash或者trie已经挂了

    那么就剩下后缀数组和自动机了(我不会啊)

    考虑一下后缀数组。。

    后缀数组原本答案等于总的子串-sigma(height[i])

    它每一次都是在末尾加入,其实也就是增加了一个前缀

    所以 就可以改成一个前缀数组(其实就是把串翻转一下)

    然后 其实就非常简单了。。

    我们可以先把整个串的height搞出来

    然后插入一个元素实际就是插入一个后缀

    那么查找到它的前一个后缀和后一个后缀,用rmq查找他们之间的lcp

    前驱后继显然是用splay维护的(因为不会set)

    考前模板题。。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define N 110000
    #define INF 5e8
    ll sa[N],a[N],c[N],x[N],y[N],rank[N],height[N],ans2[N];
    ll num2,root,n,m,bz[N][21],fa[N],leftson[N],rightson[N],data[N];
    struct re{
      ll a,b;
    }cc[N];
    void get_sa(ll n,ll m)
    {
       ll p=0,f=0;
       for (ll i=1;i<=m;i++) c[i]=0;
       for (ll i=1;i<=n;i++) c[x[i]=a[i]]++;
       for (ll i=1;i<=m;i++) c[i]+=c[i-1];
       for (ll i=n;i;i--) sa[c[x[i]]--]=i;
       for (ll i=1;i<=n&&p<=n;i<<=1)
       {
           p=0;
           for (ll j=n-i+1;j<=n;j++) y[++p]=j;
           for (ll j=1;j<=n;j++)
             if (sa[j]>i) y[++p]=sa[j]-i;
           for (ll j=1;j<=m;j++) c[j]=0;
           for (ll j=1;j<=n;j++) c[x[y[j]]]++;
           for (ll j=1;j<=m;j++) c[j]+=c[j-1];
           for (ll j=n;j;j--) sa[c[x[y[j]]]--]=y[j];
           swap(x,y); x[sa[1]]=1; p=2;
           for (ll j=2;j<=n;j++)
             x[sa[j]]=y[sa[j]]==y[sa[j-1]]&&y[sa[j]+i]==y[sa[j-1]+i]
             ?p-1:p++;
           m=p; 
       } 
       for (ll i=1;i<=n;i++) rank[sa[i]]=i;
       for (ll i=1;i<=n;i++)
       {
           ll j=sa[rank[i]-1];
           if (f) f--;
           while (a[i+f]==a[j+f]) f++;
           height[rank[i]]=f;
       }
       for (ll i=1;i<=n;i++) bz[i][0]=height[i];
       for (ll i=1;i<=20;i++)
         for (ll j=1;j<=n;j++)
           if (j+(1<<i)-1<=n)
             bz[j][i]=min(bz[j][i-1],bz[j+(1<<(i-1))][i-1]);
    } 
    ll lcp(ll a,ll b)
    {
       ll x=rank[a],y=rank[b];
       if (x>y) swap(x,y); x++;
       ll z=log2(y-x+1);
       return (min(bz[x][z],bz[y-(1<<z)+1][z]));
    }
    void rotate(ll x,ll y)
    {
       ll father=fa[x];
       if (y==1)
       {
           rightson[father]=leftson[x];
           if (leftson[x]) fa[leftson[x]]=father;
       } else
       {
           leftson[father]=rightson[x];
           if (rightson[x]) fa[rightson[x]]=father;
       }
       fa[x]=fa[father];
       if (fa[x])
       {
         if (leftson[fa[x]]==father) leftson[fa[x]]=x;
         else rightson[fa[x]]=x;
       }
       fa[father]=x;
       if (y==1) leftson[x]=father; else rightson[x]=father;
       //updata(father); updata(x);
    }
    void splay(ll x,ll goal)
    {
      if (x==root) return;
      ll father=fa[x];
      while (father!=goal)
      {
        if (fa[father]==goal)
        {
          if (x==leftson[father]) rotate(x,2); else rotate(x,1);
        } else
        {
          if (leftson[fa[father]]==father)
            if (leftson[father]==x)
              rotate(father,2),rotate(x,2);
            else rotate(x,1),rotate(x,2);
          else if (rightson[father]==x)
              rotate(father,1),rotate(x,1);
            else rotate(x,2),rotate(x,1);
        }
        father=fa[x];
      }
      if (goal==0) root=x;
    }
    void insert(ll x)
    {
      ll y=root;
      while (y)
      {
        //count2[y]++;
        if (x<data[y])
        {
            if (!leftson[y]) break;
            y=leftson[y];
        } else
        {
            if (!rightson[y]) break;
            y=rightson[y];
        }
      }
      data[++num2]=x; fa[num2]=y;
      if (x>data[y]) rightson[y]=num2;
      else leftson[y]=num2;
      splay(num2,0);
    }
    ll pre(ll x)
    {
      ll y=root,maxn=-INF;
      while (y)
      {
        if (data[y]<=x) maxn=max(maxn,data[y]);
        if (data[y]<=x) y=rightson[y];
        else y=leftson[y];
      }
      return maxn;
    }
    ll succ(ll x)
    {
      ll y=root,minn=INF;
      while (y)
      {
        if (data[y]>=x) minn=min(minn,data[y]);
        if (data[y]<=x) y=rightson[y];
        else y=leftson[y];
      }
      return minn;
    }
    bool cmp(re x,re y)
    {
       return(x.a<y.a);
    }
    int main()
    {
        cin>>n;
        for (ll i=1;i<=n;i++)
        {
          cin>>cc[i].a;
          cc[i].b=n-i+1;
        }
        sort(cc+1,cc+n+1,cmp);
        cc[0].a=-INF; ll sum=0;
        for (ll i=1;i<=n;i++)
        {
          if (cc[i].a!=cc[i-1].a) sum++;
          a[cc[i].b]=sum;
        }
        get_sa(n,n);
        ll ans=0;
        for (ll i=1;i<=n;i++)
        {
           ll x=n-i+1;
           ll x1=pre(rank[x]),x2=succ(rank[x]);
           if (x1!=-INF) x1=sa[x1],ans+=ans2[x]=lcp(x1,x);
           if (x2!=INF) x2=sa[x2],ans-=ans2[x2],ans+=ans2[x2]=lcp(x,x2);
           cout<<i*(i+1)/2-ans<<endl; 
           insert(rank[x]);
        }
        return 0;
    }
  • 相关阅读:
    小米手机4 rom 下载链接
    java 两个线程交替打印到100
    获取积分最多的人(二)
    刷题通过的题目排名
    考试分数(二)
    牛客的课程订单分析(二)
    牛客的课程订单分析(三)
    docker使用小记
    Dynamic Graph Collaborative Filtering
    Learnable Embedding Sizes for Recommender Systems
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8551689.html
Copyright © 2020-2023  润新知