[后缀数组 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
- [后缀数组 set] BZOJ 4516 [Sdoi2016]生成魔咒
- bzoj 4516: [Sdoi2016]生成魔咒 后缀数组
- bzoj 4516: [Sdoi2016]生成魔咒 后缀数组
- bzoj 4516 [Sdoi2016]生成魔咒 后缀自动机
- bzoj 4516: [Sdoi2016]生成魔咒 (后缀自动机)
- 【BZOJ 4516】 [Sdoi2016]生成魔咒 后缀自动机
- [BZOJ4516] [SDOI2016] 生成魔咒 - 后缀数组/后缀自动机
- BZOJ4516 [Sdoi2016]生成魔咒 后缀自动机/后缀数组
- BZOJ 4516: [Sdoi2016]生成魔咒
- BZOJ 4516: [Sdoi2016]生成魔咒
- BZOJ 4516 [Sdoi2016]生成魔咒
- bzoj 4516 [Sdoi2016]生成魔咒
- 【BZOJ4516】【Sdoi2016】生成魔咒 后缀数组 线段树
- BZOJ4516: [Sdoi2016]生成魔咒(后缀数组)
- 4516: [Sdoi2016]生成魔咒|后缀数组|线段树|ST表
- 【bzoj4516】[Sdoi2016]生成魔咒 后缀自动机
- 后缀自动机 【Sdoi2016】生成魔咒 bzoj4516
- BZOJ4516 [Sdoi2016]生成魔咒 后缀自动机
- linux之间互传文件(ubuntu为例)
- iOS 多线程简单使用的详解
- 动效-APP设计的肢体语言
- FreeMarker教程
- C++实验3-3
- [后缀数组 set] BZOJ 4516 [Sdoi2016]生成魔咒
- 解析ANDROID ps命令执行后各项参数的含义
- 避免同一activity下 多个fragment 切换时重复执行onCreateView方法
- 4.21日开始JAVA
- Win7虚拟无线AP以及Android手机抓包
- 20常用正则表达式
- 如何理解UX 设计中的功能动效
- 从APp跳设置界面
- 213. House Robber II