BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay
BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay
Description
Input
Output
输出 n 行,每行一个数。第 i 行的数表示第 i 次操作后 S 的生成魔咒数量
Sample Input
1 2 3 3 3 1 2
Sample Output
3
6
9
12
17
22
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- using namespace std;
- #define N 100050
- #define ls ch[p][0]
- #define rs ch[p][1]
- #define get(x) (ch[f[x]][1]==x)
- typedef long long ll;
- int n,ws[N],wv[N],wa[N],wb[N],rank[N],sa[N],height[N],r[N];
- int f[N],ch[N][2],siz[N],rt,val[N],reimu;
- //////////////////////////////////////////////
- struct A {
- int num,id,v;
- }a[N];
- bool cmp1(const A &x,const A &y){return x.num<y.num;}
- bool cmp2(const A &x,const A &y){return x.id<y.id;}
- ///////////////////////////////////////////////
- void build_suffix_array() {
- int i,j,p,*x=wa,*y=wb,*t,m=n;
- for(i=0;i<m;i++) ws[i]=0;
- for(i=0;i<n;i++) ws[x[i]=r[i]]++;
- for(i=1;i<m;i++) ws[i]+=ws[i-1];
- for(i=n-1;i>=0;i--) sa[--ws[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>=0) y[p++]=sa[i]-j;
- for(i=0;i<n;i++) wv[i]=x[y[i]];
- for(i=0;i<m;i++) ws[i]=0;
- for(i=0;i<n;i++) ws[wv[i]]++;
- for(i=1;i<m;i++) ws[i]+=ws[i-1];
- for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
- for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++) {
- if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1;
- else x[sa[i]]=p++;
- }
- }
- for(i=1;i<n;i++) rank[sa[i]]=i;
- for(i=p=0;i<n-1;height[rank[i++]]=p)
- for(p?p--:0,j=sa[rank[i]-1];r[i+p]==r[j+p];p++);
- }
- /////////////////////////////////////////////
- int newnode(int x) {
- siz[++reimu]=1; val[reimu]=x; return reimu;
- }
- void pushup(int p) {
- siz[p]=siz[ls]+siz[rs]+1;
- }
- void rotate(int x) {
- int y=f[x],z=f[y],k=get(x);
- ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
- ch[x][!k]=y; f[y]=x; f[x]=z;
- if(z) ch[z][ch[z][1]==y]=x;
- pushup(y); pushup(x);
- if(rt==y) rt=x;
- }
- void splay(int x,int y) {
- for(int fa;(fa=f[x])!=y;rotate(x))
- if(f[fa]!=y)
- rotate(get(x)==get(fa)?fa:x);
- }
- void insert(int x) {
- int p=rt,l,r;
- while(p) {
- if(val[p]>=x) r=p,p=ls;
- else l=p,p=rs;
- }
- splay(l,0); splay(r,rt);
- ch[r][0]=newnode(x);
- f[reimu]=r; pushup(r); pushup(l);
- }
- int pre(int x) {
- int p=rt,ans;
- while(p) {
- if(val[p]>=x) p=ls;
- else ans=p,p=rs;
- }
- return val[ans];
- }
- int nxt(int x) {
- int p=rt,ans;
- while(p) {
- if(val[p]<=x) p=rs;
- else ans=p,p=ls;
- }
- return val[ans];
- }
- /////////////////////////////////////////
- struct ST {
- int f[N][20],L[N];
- void init() {
- int i,j;
- memset(f,0x3f,sizeof(f));
- L[1]=0;
- for(i=2;i<=n;i++) L[i]=L[i>>1]+1;
- for(i=0;i<=n;i++) {
- f[i][0]=height[i];
- }
- for(j=1;(1<<j)<=n;j++) {
- for(i=0;i+(1<<j)-1<=n;i++) {
- f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
- }
- }
- }
- int get_min(int l,int r) {
- int len=L[r-l+1];
- return min(f[l][len],f[r-(1<<len)+1][len]);
- }
- }S;
- int main() {
- scanf("%d",&n);
- int i;
- for(i=1;i<=n;i++) scanf("%d",&a[n-i+1].num),a[i].id=i;
- sort(a+1,a+n+1,cmp1);
- int j=0;a[0].num=23333443;
- for(i=1;i<=n;i++) {
- if(a[i].num!=a[i-1].num) j++;
- a[i].v=j;
- }
- sort(a+1,a+n+1,cmp2);
- for(i=0;i<n;i++) {
- r[i]=a[i+1].v;
- }
- r[n++]=0;
- build_suffix_array();
- /*for(i=0;i<n;i++) printf("%d ",r[i]); puts("");
- for(i=0;i<n;i++) printf("%d ",sa[i]); puts("");
- for(i=0;i<n;i++) printf("%d ",height[i]); puts("");
- for(i=0;i<n;i++) printf("%d ",rank[i]);puts("");*/
- ll ans=0;
- rt=newnode(-100000000);
- ch[rt][1]=newnode(100000000);
- f[ch[rt][1]]=rt;
- pushup(rt);
- S.init();
- for(i=n-2;i>=0;i--) {
- ans+=n-i-1;
- int pr=pre(rank[i]);
- int tmp=0;
- if(pr>=0) {
- tmp=S.get_min(pr+1,rank[i]);
- }
- int nx=nxt(rank[i]);
- if(nx<=n) {
- tmp=max(tmp,S.get_min(rank[i]+1,nx));
- }
- ans-=tmp;
- insert(rank[i]);
- printf("%lld\n",ans);
- }
- }
- /*
- 7
- 1 2 3 3 3 1 2
- */
BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay的更多相关文章
- bzoj千题计划283:bzoj4516: [Sdoi2016]生成魔咒(后缀数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=4516 考虑在后面新加一个字母产生的影响 假设是第i个 如果不考虑重复,那么会增加i个不同的字符串 考 ...
- BZOJ4516 SDOI2016生成魔咒(后缀数组+平衡树)
一个字符串本质不同的子串数量显然是总子串数减去所有height值.如果一个个往里加字符的话,每次都会改动所有后缀完全没法做.但发现如果从后往前加的话,每次只会添加一个后缀.于是我们把字符串倒过来,每次 ...
- BZOJ4516 [Sdoi2016]生成魔咒 【后缀自动机】
题目 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2, ...
- cogs2223. [SDOI2016 Round1] 生成魔咒(后缀数组 hash 二分 set
题意:对一个空串每次在后面加一个字符,问每加完一次得到的字符串有几个不同的子串. 思路:每个子串都是某个后缀的前缀,对于每个后缀求出他能贡献出之前没有出现过的前缀的个数,答案累加就行. 要求每个后缀的 ...
- 2018.12.23 bzoj4516: [Sdoi2016]生成魔咒(后缀自动机)
传送门 samsamsam入门题. 题意简述:给出一个串让你依次插入字符,求每次插入字符之后不同子串的数量. 显然每次的变化量只跟新出现的nnn个后缀有关系,那么显然就是maxlenp−maxlenl ...
- [SDOI2016]生成魔咒(后缀自动机)
看一眼题.本质不同的字串数. 嘴角微微上扬. 每一次加一个数输出一个答案. 笑容渐渐消失. 等等,\(SAM\)好像也可以求本质不同的字串. 设当前字符串用\(x\)表示,每次插入完成后\(ans\) ...
- 【洛谷 P4070】 [SDOI2016]生成魔咒(后缀自动机)
题目链接 建出\(SAM\)后,不同子串个数就是\(\sum len(i)-len(fa(i))\) 因为\(SAM\)在线的,所以每加入一个字符就能直接加上其贡献,于是这道题就没了. 因为\(x\) ...
- BZOJ4516 SDOI2016生成魔咒(后缀自动机)
本质不同子串数量等于所有点的len-parent树上父亲的len的和.可以直接维护. #include<iostream> #include<cstdio> #include& ...
- [SDOI2016] 生成魔咒 - 后缀数组,平衡树,STL,时间倒流
[SDOI2016] 生成魔咒 Description 初态串为空,每次在末尾追加一个字符,动态维护本质不同的子串数. Solution 考虑时间倒流,并将串反转,则变为每次从开头删掉一个字符,即每次 ...
随机推荐
- Mac电脑配置Apache服务器详细说明
Mac电脑服务器配置过程,无论是个人学习,还是公司测试都非常实用,流程精简易懂,用于让Mac电脑做服务器方便做网络数据请求的测试. 第一步:定位到 Apache2 目录 $ cd /etc/Apach ...
- jquery-取消冒泡
1.通过返回false来取消默认的行为并阻止事件起泡. jQuery 代码: $("form").bind( "submit", function() { re ...
- PLSQL Developer使用技巧
本文由liuyk80贡献 ·PL/SQL Developer 使用技巧 1.PL/SQL Developer 记住登陆密码 在使用 PL/SQL Developer 时,为了工作方便希望 PL/SQL ...
- oracle数据库中的trim不起作用
在项目中使用datastage软件将sqlserver数据库的数据导入到oracle中的时候,出现了一些空格,然而使用trim相对应的字段发现没有作用,空格还存在,并没有去掉. 使用length(.. ...
- CSS position 笔记+实验
目录: 1.static 2.relative 3.absolute 4.fixed 5.实验:static, relative, absolute中,父元素-子元素高度关系 6.z-index 7. ...
- Day7组合
可以将那些重复的,固定的东西提出来,单独定义一个类. 例如: class Course: def __init__(self,course_name,course_period,course_pric ...
- go Mutex (互斥锁)和RWMutex(读写锁)
转载自: https://blog.csdn.net/skh2015java/article/details/60334437 golang中sync包实现了两种锁Mutex (互斥锁)和RWMute ...
- ubuntu10.04 安装oracle server 版 笔记
1:从oracle 官网下载oracle 10g ,然后解压出一个database文件夹. 2 :创建RedHat的版本声明文件[默认ubuntu无法通过oracle 的检查] 在/etc/redha ...
- C++神奇算法库——#include<algorithm>
算法(Algorithm)为一个计算的具体步骤,常用于计算.数据处理和自动推理.C++ 算法库(Algorithms library)为 C++ 程序提供了大量可以用来对容器及其它序列进行算法操作的函 ...
- 用ASP.NET Core 2.0 建立规范的 REST API
什么是REST REST 是 Representational State Transfer 的缩写. 它是一种架构的风格, 这种风格基于一套预定义的规则, 这些规则描述了网络资源是如何定义和寻址的. ...