[后缀数组 set] BZOJ 4516 [Sdoi2016]生成魔咒

来源:互联网 发布:matlab已知数据画图 编辑:程序博客网 时间:2024/05/18 15:30

将串反过来 后缀数组 然后用set维护一个序列 插入时修改答案即可


#include<cstdio>#include<cstdlib>#include<algorithm>#include<set>using namespace std;typedef long long ll;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *p1++;}inline void read(int &x){char c=nc(),b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005; int sx[N],icnt;inline int Bin(int x){return lower_bound(sx+1,sx+icnt+1,x)-sx;}int n,a[N];int sa[N],t1[N],t2[N],c[N];int height[N],rank[N];inline void SA(int *r,int m){int *x=t1,*y=t2;for (int i=0;i<=m;i++) c[i]=0;for (int i=1;i<=n;i++) c[x[i]=r[i]]++;for (int i=1;i<=m;i++) c[i]+=c[i-1];for (int i=n;i;i--) sa[c[x[i]]--]=i;for (int k=1;k<=n;k<<=1){int p=0;for (int i=n-k+1;i<=n;i++) y[++p]=i;for (int i=1;i<=n;i++) if (sa[i]>k) y[++p]=sa[i]-k;for (int i=0;i<=m;i++) c[i]=0;for (int i=1;i<=n;i++) c[x[y[i]]]++;for (int i=1;i<=m;i++) c[i]+=c[i-1];for (int i=n;i;i--) sa[c[x[y[i]]]--]=y[i];swap(x,y);x[sa[1]]=1; p=1;for (int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k])?p:++p;if (p>=n) break;m=p;}}inline void GetHeight(int *S,int *sa,int n){int j,k=0;for (int i=1;i<=n;i++) rank[sa[i]]=i;for (int i=1;i<=n;height[rank[i++]]=k)for (k?k--:0,j=sa[rank[i]-1];S[i+k]==S[j+k];)k++;}namespace ST{int st[N][20],Log[N];inline void Build(int n,int *a){for (int i=2;i<=n;i++) Log[i]=Log[i>>1]+1;for (int i=1;i<=n;i++)st[i][0]=a[i];for (int k=1;k<20;k++)for (int i=1;i<=n;i++){st[i][k]=st[i][k-1];if (i+(1<<(k-1))<=n)st[i][k]=min(st[i][k],st[i+(1<<(k-1))][k-1]);}}inline int Query(int l,int r){int t=Log[r-l+1];return min(st[l][t],st[r-(1<<t)+1][t]);}}set<int> Set;typedef set<int>::iterator ITER; int pre[N],nxt[N];ll ans,cnt[N];inline int Height(int x,int y){return ST::Query(x+1,y);}int main(){int p,now;freopen("t.in","r",stdin);freopen("t.out","w",stdout);read(n);for (int i=1;i<=n;i++)read(a[i]),sx[++icnt]=a[i];reverse(a+1,a+n+1);sort(sx+1,sx+icnt+1);icnt=unique(sx+1,sx+icnt+1)-sx-1;for (int i=1;i<=n;i++) a[i]=Bin(a[i]);SA(a,icnt);GetHeight(a,sa,n);ST::Build(n,height);Set.insert(0);for (int i=n;i;i--){now=rank[i];ITER it=Set.upper_bound(now);if (it!=Set.end()){p=*it;ans-=cnt[p];cnt[p]=(n-sa[p]+1)-Height(now,p);ans+=cnt[p];}p=*(--it);cnt[now]=(n-i+1)-Height(p,now);Set.insert(now);;ans+=cnt[now];printf("%lld\n",ans);}return 0;}


0 0
原创粉丝点击