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;
    }
    
  • 相关阅读:
    开始学习编写用于 Windows SideShow 设备的小工具【转】
    Windows Mobile 6.5 Developer Tool Kit 下载
    Microsoft Security Essentials 微软免费杀毒软件下载
    SQL Server 2008 空间数据存储摘抄(SRID 点 MultiPoint LineString MultiLineString 多边形 MultiPolygon GeometryCollection)
    Vista Sidebar Gadget (侧边栏小工具)开发教程 (2)
    Vista Sidebar Gadget (侧边栏小工具)开发教程 (4)
    负载测试、压力测试和性能测试的异同
    Windows Server 2008 Vista Sidebar Gadget (侧边栏小工具) 入门开发实例
    Silverlight Tools 安装失败 解决办法
    SQL Server 2008 空间数据库 空间索引概念及创建(取自帮助)
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7138165.html
Copyright © 2011-2022 走看看