zoukankan      html  css  js  c++  java
  • BZOJ4516:[Sdoi2016]生成魔咒

    4516: [Sdoi2016]生成魔咒

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1121  Solved: 623
    [Submit][Status][Discuss]

    Description

    魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。
    一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。
    例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生成魔咒有 [1]、
    [1,1]、[1,1,1] 三种。最初 S 为空串。共进行 n 次操作,每次操作是在 S 的结尾加入一个魔咒字符。每次操作后都
    需要求出,当前的魔咒串 S 共有多少种生成魔咒。

    Input

    第一行一个整数 n。
    第二行 n 个数,第 i 个数表示第 i 次操作加入的魔咒字符。
    1≤n≤100000。,用来表示魔咒字符的数字 x 满足 1≤x≤10^9

    Output

    输出 n 行,每行一个数。第 i 行的数表示第 i 次操作后 S 的生成魔咒数量

    Sample Input

    7
    1 2 3 3 3 1 2

    Sample Output

    1
    3
    6
    9
    12
    17
    22
    思路{
      我们可以轻松求出插入之后的本质不同的子串个数。
      怎么乱搞呢?
      我们从后往前考虑:{
        加入一个数就是加入一个后缀:那我们直接统计这个后缀的贡献值都可以了。
        在非动态的情况下,每一个的贡献是n-height[i]+1;
        在动态的情况下,那每个的贡献就是(n-(rnk的前驱或后继)的LCP最大值+1);
        那我们用set或treap或Splay维护一下即可。
      }
    }
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #define inf (1<<30)
    #define il inline
    #define RG register
    #define db double
    #define LL long long
    #define maxx 100010
    using namespace std;
    set<LL> q;
    set<LL>::iterator it;
    LL a[maxx],tong[maxx],X[maxx],Y[maxx],height[maxx],rnk[maxx],f[maxx][19],pre[maxx],nxt[maxx],ans[maxx],sa[maxx];
    il bool comp(LL *r,LL a,LL b,LL len){return r[a]==r[b]&&r[len+b]==r[len+a];}
    il void build_sa(LL n){
    	LL *x=X,*y=Y,*t,Max=maxx-1;
    	for(RG LL i=0;i<n;++i)tong[x[i]=a[i]]++;
    	for(RG LL i=1;i<=Max;++i)tong[i]+=tong[i-1];
    	for(RG LL i=n-1;i!=-1;i--)sa[--tong[x[i]]]=i;
    	for(RG LL j=1,i,p=0;p<n;j<<=1,Max=p){
    		for(i=n-1,p=0;i>=n-j;--i)y[p++]=i;
    		for(i=0;i<n;++i)if(sa[i]>=j)y[p++]=sa[i]-j;
    		for(i=0;i<=Max;++i)tong[i]=0;
    		for(i=0;i<n;++i)tong[x[y[i]]]++;
    		for(i=1;i<=Max;++i)tong[i]+=tong[i-1];
    		for(i=n-1;i>=0;i--)sa[--tong[x[y[i]]]]=y[i];
    		for(i=1,p=1,t=x,x=y,y=t,x[sa[0]]=0;i<n;++i)
    			x[sa[i]]=comp(y,sa[i-1],sa[i],j)?p-1:p++;
    	}
    }
    LL n;
    il void geth(){
    	RG LL i,j,k=0;
    	for(i=1;i<=n;++i)rnk[sa[i]]=i;
    	for(i=0;i<n;height[rnk[i++]]=k)
    		for((k?k--:0),j=sa[rnk[i]-1];a[j+k]==a[i+k];k++);
    }
    void RMQ(){
      for(int i=1;i<=n;++i)f[i][0]=height[i];
      for(int j=1;(1<<j)<=n;++j)
        for(int i=1;i+(1<<(j-1))-1<=n;++i)
          f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    }
    LL LCP(int x,int y){
      if(x==y)return n-x+1; 
      x=rnk[x],y=rnk[y];if(x>y)swap(x,y);x++;
      int t=(int)(log(double(y-x+1))/log(2.000));
      return min(f[x][t],f[y-(1<<t)+1][t]);
    }
    il void update(LL x,LL y,LL kind){x=sa[x],y=sa[y];if(kind)pre[x]=y;else nxt[x]=y;}
    LL sub[maxx];
    il void luangao(){
    	for(int i=0;i<n;++i)sub[i]=a[i];  
        sort(sub,sub+n);  int size=unique(sub,sub+n)-sub;  
        for(int i=0;i<n;i++)  
        a[i]=lower_bound(sub,sub+size,a[i])-sub+1;
    }
    il void work(){
    	scanf("%lld",&n);
    	for(RG LL i=n-1;i!=-1;--i)scanf("%lld",&a[i]);luangao();
    	a[n]=0;build_sa(n+1),geth();RMQ();
    	for(RG LL i=n-1;i!=-1;i--){
    		bool flag1=false,flag2=false;
    		q.insert(rnk[i]),it=q.find(rnk[i]);
    		if(it!=q.begin())it--,update(rnk[i],*it,1),it++,flag1=true;
    		if((++it)!=q.end())update(rnk[i],*it,0),flag2=true;
    		LL now=n-i,lcp=0;if(flag1)lcp=LCP(i,pre[i]);
    		if(flag2)lcp=max(lcp,LCP(i,nxt[i]));
    		ans[now]=now-lcp+ans[now-1];
    	}for(RG LL i=1;i<=n;++i)cout<<ans[i]<<"
    ";
    }
    int main(){
    	freopen("menci_incantation.in","r",stdin);
    	freopen("menci_incantation.out","w",stdout);
        work();return 0;
    }
    
  • 相关阅读:
    (04)-Python3之--字典(dict)操作
    word2vec简单介绍
    基于websocket爬虫
    Python数据结构之链表(1)-->单链表
    词云wordcloud
    Neo4j--第一章
    AHP(层次分析法) 附Python示例代码(觉得还可以的,帮忙点个赞,谢谢)
    几种归一化方法(Normalization Method)python实现
    EM算法之Python
    通俗易懂的EM
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7138165.html
Copyright © 2011-2022 走看看