• [SDOI2016]生成魔咒


    题目描述

    魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 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 共有多少种生成魔咒。

    输入输出格式

    输入格式:

    第一行一个整数 n。

    第二行 n 个数,第 i 个数表示第 i 次操作加入的魔咒字符。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    7
    1 2 3 3 3 1 2
    输出样例#1: 复制
    1
    3
    6
    9
    12
    17
    22

    说明

    对于%10的数据,1≤n≤101 le n le 101n10

    对于%30的数据,1≤n≤1001 le n le 1001n100

    对于%60的数据,1≤n≤1001 le n le 1001n100

    对于%100的数据,1≤n≤1000001 le n le 1000001n100000

    用来表示魔咒字符的数字 x 满足1≤n≤1091 le n le 10^91n109

    反转字符串,这样就变成了后缀

    先后缀数组求出height数组

    然后从前往后一个一个加

    首先我们知道一个字符串的字串数是每个后缀的长度减去height[i]

    每加入一个字符,就新产生一个后缀

    那么每添加一个前缀,增加了多少个不同的子串,其实就是在之前添加的前缀中

    排名最靠近该前缀的两个串a和b,计算出他们与该前缀的lcp,

    然后不同的子串数就是当前添加的前缀长度len-max(lcpa,lcpb)了

    找排名最靠近的用线段树

    以后模板改了,从1开始,方便很多

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<set>
      7 using namespace std;
      8 typedef long long lol;
      9 int n,m,c[100001],x[100001],y[100001],SA[100001],s[100001],b[100001],rank[100001],h[100001];
     10 int Mx[400001],Mi[400001],Log[100001],Min[100001][21];
     11 lol ans;
     12 void radix_sort()
     13 {int i;
     14   for (i=0;i<=m;i++)
     15     c[i]=0;
     16   for (i=1;i<=n;i++)
     17     c[x[y[i]]]++;
     18   for (i=2;i<=m;i++)
     19     c[i]+=c[i-1];
     20   for (i=n;i>=1;i--)
     21     SA[c[x[y[i]]]--]=y[i];
     22 }
     23 void build_SA()
     24 {int i,j,k,p;
     25   for (i=1;i<=n;i++)
     26     x[i]=s[i],y[i]=i;
     27   m=100000;
     28   radix_sort();
     29   for (k=1;k<=n;k<<=1)
     30     {
     31       p=0;
     32       for (i=n-k+1;i<=n;i++)
     33     y[++p]=i;
     34       for (i=1;i<=n;i++)
     35     if (SA[i]>k) y[++p]=SA[i]-k;
     36       radix_sort();
     37       p=1;swap(x,y);
     38       x[SA[1]]=1;
     39       for (i=2;i<=n;i++)
     40     x[SA[i]]=((y[SA[i]]==y[SA[i-1]])&&(y[SA[i]+k]==y[SA[i-1]+k]))?p:++p;
     41       if (p>=n) break;
     42       m=p;
     43     }
     44   for (i=1;i<=n;i++)
     45     rank[SA[i]]=i;
     46   int L=0;
     47   for (i=1;i<=n;i++)
     48     {
     49       if (L>0) L--;
     50       j=SA[rank[i]-1];
     51       while (i+L<=n&&j+L<=n&&(s[j+L]==s[i+L])) L++;
     52       h[rank[i]]=L;
     53     }
     54 }
     55 void update(int rt,int l,int r,int x)
     56 {
     57   if (l==r)
     58     {
     59       Mx[rt]=Mi[rt]=x;
     60       return;
     61     }
     62   int mid=(l+r)/2;
     63   if (x<=mid) update(rt<<1,l,mid,x);
     64   else update(rt<<1|1,mid+1,r,x);
     65   Mx[rt]=max(Mx[rt<<1],Mx[rt<<1|1]);
     66   Mi[rt]=min(Mi[rt<<1],Mi[rt<<1|1]);
     67 }
     68 int query(int rt,int l,int r,int L,int R,int p)
     69 {
     70   if (l>=L&&r<=R)
     71     {
     72       if (p==1)
     73     return Mx[rt];
     74       else return Mi[rt];
     75     }
     76   int mid=(l+r)/2,mx=0,mi=n+1;
     77   if (p==1)
     78     {
     79       if (L<=mid) mx=max(mx,query(rt<<1,l,mid,L,R,p));
     80       if (R>mid) mx=max(mx,query(rt<<1|1,mid+1,r,L,R,p));
     81       return mx;
     82     }
     83   else
     84     {
     85       if (L<=mid) mi=min(mi,query(rt<<1,l,mid,L,R,p));
     86       if (R>mid) mi=min(mi,query(rt<<1|1,mid+1,r,L,R,p));
     87       return mi;
     88     }
     89 }
     90 int RMQ(int x,int y)
     91 {
     92   int L=Log[y-x+1];
     93   return min(Min[x][L],Min[y-(1<<L)+1][L]);
     94 }
     95 int main()
     96 {int i,tot,j,tmp;
     97   //freopen("zyys.out","w",stdout);
     98   scanf("%d",&n);
     99   for (i=1;i<=n;i++)
    100     {
    101       scanf("%d",&s[n-i+1]);
    102       b[i]=s[n-i+1];
    103     }
    104   sort(b+1,b+n+1);
    105   tot=unique(b+1,b+n+1)-b-1;
    106   for (i=1;i<=n;i++)
    107     s[i]=lower_bound(b+1,b+tot+1,s[i])-b;
    108   build_SA();
    109   Log[1]=0;
    110   for (i=2;i<=n;i++)
    111     Log[i]=Log[i/2]+1;
    112   for (i=1;i<=n;i++)
    113     Min[i][0]=h[i];
    114   for (j=1;(1<<j)<=n;j++)
    115     {
    116       for (i=1;i<=n-(1<<j)+1;i++)
    117     Min[i][j]=min(Min[i][j-1],Min[i+(1<<j-1)][j-1]);
    118     }
    119   memset(Mx,-127/2,sizeof(Mx));memset(Mi,127/2,sizeof(Mi));
    120   update(1,0,n+1,0);update(1,0,n+1,n+1);
    121   for (i=n;i>=1;i--)
    122     {
    123       int now=rank[i];
    124       int pre=query(1,0,n+1,0,now-1,1),nxt=query(1,0,n+1,now+1,n+1,2);
    125       tmp=0;
    126       if (pre>=1)
    127       tmp=max(tmp,RMQ(pre+1,now));
    128       if (nxt<=n)
    129       tmp=max(tmp,RMQ(now+1,nxt));
    130       ans+=n-i+1-tmp;
    131       printf("%lld
    ",ans);
    132       update(1,0,n+1,now);
    133     }
    134 }
  • 相关阅读:
    Vue--运行项目发送http://localhost:8080/sockjs-node/info请求报错,造成浏览器不能热更新
    Vue笔记--同局域网下访问本地项目
    Vue笔记--通过自定义指令实现按钮操作权限
    css/css3实现未知宽高元素的垂直居中和水平居中
    【转载】Vue路由history模式踩坑记录:nginx配置解决404问题
    给动态生成的input框,添加readonly属性
    layui-form下隐藏元素的验证问题
    layui的省市县三级联动
    webstorm-激活码
    采坑
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8509648.html
Copyright © 2020-2023  润新知