记录编号 |
372143 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[SDOI 2016 Round1] 生成魔咒 |
最终得分 |
100 |
用户昵称 |
甘罗 |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.689 s |
提交时间 |
2017-02-17 19:27:56 |
内存使用 |
24.73 MiB |
显示代码纯文本
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>
#include<cmath>
#define N 200010
using namespace std;
int i,len;
set <int> v;
int c[N],C[N],a[N],f[N][20],fh[N],fq[N];
int sa[N],rank[N],height[N],wa[N],wb[N],wv[N],ss[N];
inline int Min(int a,int b){return (a<b)?a:b;}
inline int cmp(int *r,int x,int y,int l){return (r[x]==r[y]&&r[x+l]==r[y+l]);}
inline int read(){
int p=0; char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9') p=p*10+c-48,c=getchar();
return p;
}
inline int Query(int x,int y){
int p=(int)(log(y-x+1)/log(2));
return Min(f[x][p],f[y+1-(1<<p)][p]);
}
inline int Pred(int x){
set <int>::const_iterator y=v.lower_bound(x);
if (y!=v.begin()) return *--y;
else return 0;
}
inline int Succ(int x){
set <int>::const_iterator y=v.lower_bound(x);
if (y!=v.end()) return *y;
else return 0;
}
inline void SA(int *r,int *sa,int n,int m){
int i,j,p,*t,*x=wa,*y=wb;
for (i=0;i<m;i++) ss[i]=0;
for (i=0;i<n;i++) ss[x[i]=r[i]]++;
for (i=1;i<m;i++) ss[i]+=ss[i-1];
for (i=n-1;i>=0;i--) sa[--ss[x[i]]]=i;
for (j=p=1;p<n;j<<=1,m=p){
for (p=0,i=n-j;i<n;i++) y[p++]=i;
for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
for (i=0;i<n;i++) wv[i]=x[y[i]];
for (i=0;i<m;i++) ss[i]=0;
for (i=0;i<n;i++) ss[wv[i]]++;
for (i=1;i<m;i++) ss[i]+=ss[i-1];
for (i=n-1;i>=0;i--) sa[--ss[wv[i]]]=y[i];
for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
}
inline void HA(int *r,int *sa,int n){
int i,j,k=0;
for (i=1;i<=n;i++) rank[sa[i]]=i;
for (i=0;i<n;height[rank[i++]]=k)
for (k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
inline void Ready(){
int i=0,j=0;
for (i=1;i<=len;i++) f[i][0]=height[i];
for (j=1;(1<<j)<len;j++)
for (i=1;i<=len-j;i++)
f[i][j]=Min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
for (i=1;i<len;i++) fh[i]=i+1;
for (i=2;i<=len;i++) fq[i]=i-1;
}
inline void Work(){
int i=0,j=0,x=0,y=0,cnt=0;
for (i=len-1;i>=0;i--){
j=rank[i]; x=Pred(j); y=Succ(j);
if (x!=0&&y!=0) cnt-=Query(x+1,y);
if (x!=0) cnt+=Query(x+1,j);
if (y!=0) cnt+=Query(j+1,y);
v.insert(j);
printf("%lld\n",(long long)(len-i)*(len-i+1)/2-(long long)cnt);
}
}
int main(){
freopen("menci_incantation.in","r",stdin);
freopen("menci_incantation.out","w",stdout);
len=read();
for (i=0;i<len;i++) c[i]=read(),a[i]=c[i];
sort(a,a+len);
int *end=unique(a,a+len);
for (i=0;i<len;i++) C[len-1-i]=lower_bound(a,end,c[i])-a+1;
C[len]=0;
SA(C,sa,len+1,len+1); HA(C,sa,len);
Ready(); Work();
return 0;
}