[后缀数组 set] BZOJ 4516 [Sdoi2016]生成魔咒
2016-04-22 10:29
369 查看
将串反过来 后缀数组 然后用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 ,icnt; inline int Bin(int x) { return lower_bound(sx+1,sx+icnt+1,x)-sx; } int n,a ; int sa ,t1 ,t2 ,c ; int height ,rank ; 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 [20],Log ; 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 ,nxt ; ll ans,cnt ; 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; }
相关文章推荐
- 方法(面向对象篇)
- 如何理解UX 设计中的功能动效
- Storm记录级容错的基本原理(acker工作原理)
- 关于注解@ResponseBody 和 @RequestMapping
- 使用Cocos开发一款简单的3D VR抓钱游戏
- 查找与排序
- 自己的菜单,阻止默认事件
- 【Kylin实战】邮件报表生成
- 20常用正则表达式
- 如何算是脚本正确的执行——记一次新员工考核
- 输错密码?这个 sudo 会“嘲讽”你
- 避免同一activity下 多个fragment 切换时重复执行onCreateView方法
- Java层Binder使用(ServiceManager)
- OpenStack for NFV applications: enabling Single Root I/O virtualization and PCI-Passthrough
- 动效-APP设计的肢体语言
- C++实验3-3
- [CareerCup] 17.5 Game of Master Mind 猜字游戏
- Linux chattr锁定关键的系统文件
- 学习笔记之加密解密,PKI,CA
- spring框架中web.xml的配置详解