4516: [Sdoi2016]生成魔咒
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1532 Solved: 885
[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
1 2 3 3 3 1 2
Sample Output
1
3
6
9
12
17
22
3
6
9
12
17
22
维护答案的错误写法
1 for(int j=lst+1;j<= cnt;++j)ans+=(l[j]-l[f[j]]); 2 lst=cnt;
毕竟每次插入字符时之前的父子关系、转移关系会改变啦
1 /************************************************************** 2 Problem: 4516 3 User: xln 4 Language: C++ 5 Result: Accepted 6 Time:820 ms 7 Memory:15720 kb 8 ****************************************************************/ 9 10 #include<cstdio> 11 #include<iostream> 12 #include<algorithm> 13 #include<map> 14 using namespace std; 15 const int N=200005; 16 map<int,int>c[N]; 17 int pre=1,cnt=1,f[N],l[N],s[N],n; 18 typedef long long ll; 19 ll ans; 20 inline int gi(){int d=0;char c=getchar();while(c<'0'||c>'9')c=getchar(); 21 while(c<='9'&&c>='0'){d=(d<<3)+(d<<1)+c-'0';c=getchar();}return d;} 22 inline void ins(int x){ 23 int p=pre,np=++cnt;pre=np;l[np]=l[p]+1; 24 for(;p&&!c[p].count(x);p=f[p])c[p][x]=np; 25 if(!p)f[np]=1; 26 else{ 27 int q=c[p][x]; 28 if(l[q]==l[p]+1)f[np]=q; 29 else{ 30 int nq=++cnt; 31 c[nq]=c[q]; 32 f[nq]=f[q]; 33 l[nq]=l[p]+1; 34 ans-=(l[q]-l[f[q]]); 35 f[q]=f[np]=nq; 36 ans+=(l[q]-l[f[q]]); 37 ans+=(l[nq]-l[f[nq]]); 38 for(;c[p][x]==q;p=f[p])c[p][x]=nq; 39 } 40 } 41 ans+=(l[np]-l[f[np]]); 42 } 43 int main(){ 44 n=gi(); 45 for(int i=1;i<=n;++i){ 46 s[i]=gi(); 47 ins(s[i]); 48 printf("%lld ",ans); 49 } 50 return 0; 51 }