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

    4516: [Sdoi2016]生成魔咒

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 710  Solved: 393
    [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
     
    题解
    这题就是求有多少个不同子串……不过首先我不会SAM,其次pascal没有set
    于是我就用后缀数组+fhqtreap强行写了一发……首先把串反过来跑后缀数组求出h数组,之后每次插入一个字符就是相当于多了一个新后缀,查一下这个后缀在当前已加入的后缀里rank的前驱后继,然后求一下最长公共前缀,后缀长度减去最长公共前缀就是加入一个字符所增加的子串个数
    1A赞啊>_<
      1 program j01;
      2 const maxn=100086;
      3 type xx=record w,id:longint; end;
      4 var op:array[0..maxn]of xx;
      5     sa,tsa,rank,trank,sum,s,mn,h:array[0..maxn]of longint;
      6     st:array[0..20,0..maxn]of longint;
      7     len,tot,i,l,r,root,k1,k2:longint;
      8     t:array[0..maxn]of record f,w,l,r:longint; end;
      9     ans:array[0..maxn]of int64;
     10     now,tmp:int64;
     11 
     12 procedure swap(var a,b:longint);
     13 var c:longint;
     14 begin
     15   c:=a;a:=b;b:=c;
     16 end;
     17 
     18 function max(a,b:longint):longint;
     19 begin
     20   if a>b then exit(a) else exit(b);
     21 end;
     22 
     23 function min(a,b:longint):longint;
     24 begin
     25   if a<b then exit(a) else exit(b);
     26 end;
     27 
     28 procedure qsort(l,r:longint);
     29 var i,j,x:longint;y:xx;
     30 begin
     31   i:=l;j:=r;x:=op[(i+j)div 2].w;
     32   repeat
     33     while op[i].w<x do inc(i);
     34     while x<op[j].w do dec(j);
     35     if i<=j then
     36     begin
     37       y:=op[i];op[i]:=op[j];op[j]:=y;
     38       inc(i);dec(j);
     39     end;
     40   until i>j;
     41   if i<r then qsort(i,r);
     42   if l<j then qsort(l,j);
     43 end;
     44 
     45 procedure disc;
     46 var i:longint;
     47 begin
     48   qsort(1,len);
     49   tot:=1;s[op[1].id]:=1;
     50   for i:=2 to len do
     51   begin
     52     if(op[i].w<>op[i-1].w)then inc(tot);
     53     s[op[i].id]:=tot
     54   end;
     55 end;
     56 
     57 procedure getsa;
     58 var i,j,m,p:longint;
     59 begin
     60   fillchar(sum,sizeof(sum),0);m:=tot;
     61   for i:=1 to len do rank[i]:=s[i];
     62   for i:=1 to len do inc(sum[rank[i]]);
     63   for i:=1 to m do inc(sum[i],sum[i-1]);
     64   for i:=len downto 1 do
     65   begin
     66     sa[sum[rank[i]]]:=i;dec(sum[rank[i]]);
     67   end;
     68   m:=1;trank[sa[1]]:=1;
     69   for i:=2 to len do
     70   begin
     71     if(rank[sa[i]]<>rank[sa[i-1]])then inc(m);
     72     trank[sa[i]]:=m;
     73   end;
     74   j:=1;rank:=trank;
     75   while m<len do
     76   begin
     77     fillchar(sum,sizeof(sum),0);p:=0;
     78     for i:=len-j+1 to len do
     79     begin
     80       inc(p);tsa[p]:=i;
     81     end;
     82     for i:=1 to len do
     83       if sa[i]>j then
     84       begin
     85         inc(p);tsa[p]:=sa[i]-j;
     86       end;
     87     for i:=1 to len do inc(sum[rank[i]]);
     88     for i:=1 to m do inc(sum[i],sum[i-1]);
     89     for i:=len downto 1 do
     90     begin
     91       sa[sum[rank[tsa[i]]]]:=tsa[i];dec(sum[rank[tsa[i]]]);
     92     end;
     93     m:=1;trank[sa[1]]:=1;
     94     for i:=2 to len do
     95     begin
     96       if(rank[sa[i]]<>rank[sa[i-1]])or(rank[sa[i]+j]<>rank[sa[i-1]+j])then
     97         inc(m);
     98       trank[sa[i]]:=m;
     99     end;
    100     j:=j*2;rank:=trank;
    101   end;
    102 end;
    103 
    104 procedure geth;
    105 var i,j,k:longint;
    106 begin
    107   k:=0;
    108   for i:=1 to len do
    109   begin
    110     if rank[i]=1 then
    111     begin
    112       h[rank[i]]:=0;continue;
    113     end;
    114     j:=sa[rank[i]-1];
    115     while(s[i+k]=s[j+k])do inc(k);
    116     h[rank[i]]:=k;
    117     if k>0 then dec(k);
    118   end;
    119 end;
    120 
    121 procedure getst;
    122 var i,j,a,b:longint;
    123 begin
    124   mn[0]:=-1;
    125   for i:=1 to len do
    126     if i and(i-1)=0 then mn[i]:=mn[i-1]+1 else mn[i]:=mn[i-1];
    127   for i:=1 to len do st[0,i]:=h[i];
    128   for i:=1 to mn[len] do
    129     for j:=1 to len+1-(1 shl i) do
    130       st[i,j]:=min(st[i-1,j],st[i-1,j+(1 shl(i-1))]);
    131 end;
    132 
    133 function ask(a,b:longint):longint;
    134 var d:longint;
    135 begin
    136   if a>b then swap(a,b);
    137   d:=mn[b-a+1];
    138   exit(min(st[d,a],st[d,b-(1 shl d)+1]));
    139 end;
    140 
    141 procedure split(i,x:longint;var k1,k2:longint);
    142 begin
    143   if i=0 then
    144   begin
    145     k1:=0;k2:=0;exit;
    146   end;
    147   if t[i].w<x then
    148   begin
    149     k1:=i;split(t[i].r,x,t[i].r,k2);
    150   end else
    151   begin
    152     k2:=i;split(t[i].l,x,k1,t[i].l);
    153   end;
    154 end;
    155 
    156 function merge(x,y:longint):longint;
    157 begin
    158   if(x=0)and(y=0) then exit(x+y);
    159   if t[x].f>t[y].f then
    160   begin
    161     t[x].r:=merge(t[x].r,y);exit(x);
    162   end else
    163   begin
    164     t[y].l:=merge(x,t[y].l);exit(y);
    165   end;
    166 end;
    167 
    168 begin
    169   randomize;
    170   readln(len);
    171   for i:=1 to len do
    172   begin
    173     read(s[i]);op[i].id:=i;op[i].w:=s[i];
    174   end;
    175   disc;for i:=1 to len div 2 do swap(s[i],s[len-i+1]);
    176   getsa;geth;
    177   getst;
    178   root:=0;
    179   for i:=len downto 1 do
    180   begin
    181     split(root,rank[i],k1,k2);
    182     l:=k1;while t[l].r>0 do l:=t[l].r;
    183     r:=k2;while t[r].l>0 do r:=t[r].l;
    184     t[i].f:=random(maxlongint);t[i].w:=rank[i];
    185     root:=merge(merge(k1,i),k2);
    186     tmp:=0;
    187     if l>0 then tmp:=max(tmp,ask(rank[l]+1,rank[i]));
    188     if r>0 then tmp:=max(tmp,ask(rank[i]+1,rank[r]));
    189     now:=now+len-i+1-tmp;
    190     writeln(now);
    191   end;
    192 end.
  • 相关阅读:
    【科技】扩展Lucas随想
    【NOI 2018】屠龙勇士(扩欧)
    【NOI 2018】冒泡排序(组合数学)
    【NOI 2018】归程(Kruskal重构树)
    【APIO 2018】铁人两项(圆方树)
    【科技】KD-tree随想
    UOJ#207. 共价大爷游长沙 LCT
    UOJ#23. 【UR #1】跳蚤国王下江南 仙人掌 Tarjan 点双 圆方树 点分治 多项式 FFT
    UOJ#33. 【UR #2】树上GCD 点分治 莫比乌斯反演
    UOJ#191. 【集训队互测2016】Unknown 点分治 分治 整体二分 凸包 计算几何
  • 原文地址:https://www.cnblogs.com/oldjang/p/6358784.html
Copyright © 2011-2022 走看看