BZOJ4516 SDOI2016生成魔咒(后缀数组+平衡树)
一个字符串本质不同的子串数量显然是总子串数减去所有height值。如果一个个往里加字符的话,每次都会改动所有后缀完全没法做。但发现如果从后往前加的话,每次只会添加一个后缀。于是我们把字符串倒过来,每次往里添加后缀并维护答案。可以用一棵平衡树,每次插入时查询这个名次的前驱后继以更新。
SA板子敲得磕磕绊绊,没什么救了。
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstdlib>
- #include<cstring>
- #include<algorithm>
- #include<set>
- using namespace std;
- int read()
- {
- int x=,f=;char c=getchar();
- while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
- while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
- return x*f;
- }
- #define N 100010
- int n,a[N],b[N],cnt[N],sa[N],sa2[N],tmp[N<<],rk[N<<];
- int h[N],s[N],f[N][],lg2[N];
- set<int> tree;
- int query(int x,int y)
- {
- if (x>y) swap(x,y);
- y--;
- return min(f[x][lg2[y-x+]],f[y-(<<lg2[y-x+])+][lg2[y-x+]]);
- }
- void make(int m)
- {
- memset(cnt,,sizeof(cnt));
- for (int i=;i<=n;i++) cnt[rk[i]=a[i]]++;
- for (int i=;i<=m;i++) cnt[i]+=cnt[i-];
- for (int i=n;i>=;i--) sa[cnt[rk[i]]--]=i;
- for (int k=;k<=n;k<<=)
- {
- int p=;
- for (int i=n-k+;i<=n;i++) sa2[++p]=i;
- for (int i=;i<=n;i++) if (sa[i]>k) sa2[++p]=sa[i]-k;
- memset(cnt,,sizeof(cnt));
- for (int i=;i<=n;i++) cnt[rk[i]]++;
- for (int i=;i<=m;i++) cnt[i]+=cnt[i-];
- for (int i=n;i>=;i--) sa[cnt[rk[sa2[i]]]--]=sa2[i];
- memcpy(tmp,rk,sizeof(rk));
- p=;rk[sa[]]=;
- for (int i=;i<=n;i++)
- {
- if (tmp[sa[i]]!=tmp[sa[i-]]||tmp[sa[i]+k]!=tmp[sa[i-]+k]) p++;
- rk[sa[i]]=p;
- }
- if (p>=n) break;
- m=p;
- }
- for (int i=;i<=n;i++)
- {
- h[i]=max(h[i-]-,);
- while (a[i+h[i]]==a[sa[rk[i]-]+h[i]]) h[i]++;
- }
- for (int i=;i<n;i++) f[i][]=h[sa[i+]];
- for (int j=;j<;j++)
- for (int i=;i<n;i++)
- f[i][j]=min(f[i][j-],f[min(n-,i+(<<j-))][j-]);
- lg2[]=;
- for (int i=;i<n;i++)
- {
- lg2[i]=lg2[i-];
- if ((<<lg2[i])<=i) lg2[i]++;
- }
- }
- int main()
- {
- freopen("bzoj4516.in","r",stdin);
- freopen("bzoj4516.out","w",stdout);
- n=read();
- for (int i=;i<=n;i++) b[i]=a[i]=read();
- sort(b+,b+n+);
- int t=unique(b+,b+n+)-b;
- for (int i=;i<=n;i++) a[i]=lower_bound(b+,b+t,a[i])-b;
- reverse(a+,a+n+);
- make(t);
- tree.clear();tree.insert(rk[n]);
- long long ans=;cout<<ans<<endl;
- for (int i=n-;i>=;i--)
- {
- set<int>::iterator it=tree.lower_bound(rk[i]);
- ans+=n-i+;
- if (it==tree.begin()) ans-=query(rk[i],*it);
- else if (it==tree.end()) ans-=query(rk[i],*(--it));
- else
- {
- int x=*it,y=*(--it);
- ans+=query(x,y);
- ans-=query(x,rk[i]),ans-=query(y,rk[i]);
- }
- tree.insert(rk[i]);
- printf("%lld\n",ans);
- }
- fclose(stdin);fclose(stdout);
- return ;
- }
BZOJ4516 SDOI2016生成魔咒(后缀数组+平衡树)的更多相关文章
- [SDOI2016] 生成魔咒 - 后缀数组,平衡树,STL,时间倒流
[SDOI2016] 生成魔咒 Description 初态串为空,每次在末尾追加一个字符,动态维护本质不同的子串数. Solution 考虑时间倒流,并将串反转,则变为每次从开头删掉一个字符,即每次 ...
- BZOJ4516: [Sdoi2016]生成魔咒(后缀数组 set RMQ)
题意 题目链接 Sol 毒瘤SDOI 终于有一道我会做的题啦qwq 首先,本质不同的子串的个数 $ = \frac{n(n + 1)}{2} - \sum height[i]$ 把原串翻转过来,每次就 ...
- BZOJ4516: [Sdoi2016]生成魔咒 后缀自动机
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...
- 【bzoj4516】[Sdoi2016]生成魔咒 后缀数组+倍增RMQ+STL-set
题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2].一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2 ...
- [bzoj4516][Sdoi2016]生成魔咒——后缀自动机
Brief Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生 ...
- BZOJ 4516: [Sdoi2016]生成魔咒——后缀数组、并查集
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4516 题意 一开始串为空,每次往串后面加一个字符,求本质不同的子串的个数,可以离线.即长度为 ...
- BZOJ.4516.[SDOI2016]生成魔咒(后缀数组 RMQ)
题目链接 后缀自动机做法见这(超好写啊). 后缀数组是可以做的: 本质不同的字符串的个数为 \(子串个数-\sum_{ht[i]}\),即 \(\frac{n(n+1)}{2}-\sum_{ht[i] ...
- BZOJ 4516: [Sdoi2016]生成魔咒(后缀数组)
传送门 解题思路 题目其实就是动态维护本质不同的串的个数.考虑到只有加数字的操作,所以可以用后缀数组.题目是每次往后加数字,这样不好处理,因为每次加数字之后所有的后缀都会改变.所以要转化一下思路,就是 ...
- BZOJ 4516: [Sdoi2016]生成魔咒 [后缀自动机]
4516: [Sdoi2016]生成魔咒 题意:询问一个字符串每个前缀有多少不同的子串 做了一下SDOI2016R1D2,题好水啊随便AK 强行开map上SAM 每个状态的贡献就是\(Max(s)-M ...
- liberOJ #2033. 「SDOI2016」生成魔咒 后缀数组
#2033. 「SDOI2016」生成魔咒 题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 11.2 22 拼凑起来形成一个魔咒串 [1,2] [1, 2] ...
随机推荐
- SkylineGlobe MFC C++ 开发示例代码
SkylineGlobe的SDK底层是跨平台的C++内核,面向不同平台封装原生的API,具有很高的执行效率, 下面是C++二次开发时的示例代码: #import "D:\Program Fi ...
- jQuery与js例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Matplotlib 简单图例
图例参考:http://matplotlib.org/gallery.html API参考:http://matplotlib.org/api/pyplot_summary.html # -*- co ...
- Luogu1967 NOIP2013 货车运输 最大生成树、倍增
传送门 题意:给出一个$N$个节点.$M$条边的图,$Q$次询问,每一次询问两个点之间的所有可行路径中经过的边的边权的最小值中的最大值.$N \leq 10000 , M \leq 50000 , Q ...
- .NET和F#周报第35周-.NET 8月重大更新
来看看8月份最后一个周F#和.NET最新相关信息. https://www.yuque.com/rock/fsharp-weekly/35 这次我们多聊聊.NET相关的东西, 看看.NET的健康生态. ...
- 实现Repeater控件的记录单选
有朋友问及,在Repeater控件中第一列放置一个RadioButton,实现对记录的单选. 下面Insus.NET想举个例子来实现与说明. 为Repeater控件准备数据: 在ASPX网页上,写好R ...
- IOC框架之 Unity 入门
十年河东,十年河西,莫欺少年穷 学无止境,精益求精 Unity是什么? Unity是patterns & practices团队开发的一个轻量级.可扩展的依赖注入容器,具有如下的特性: 1. ...
- Linux常用基础命令整理:关机命令、查看目录下文件命令等
Linux常用基础命令整理:关机命令.查看目录下文件命令等 整理了一些Linux常用基础命令,欢迎指正. 首先记住四个热键,学会这四个键,收益一辈子. Tab按键---命令补齐功能Ctrl+c按键-- ...
- 快速零配置迁移 API 适配 iOS 对 IPv6 以及 HTTPS 的要求
本文快速分享一下快速零配置迁移 API 适配 iOS 对 IPv6 以及 HTTPS 的要求的方法,供大家参考. 原文发表于我的技术博客 零配置方案 最新的苹果审核政策对 API 的 IPv6 以及 ...
- Linux服务器更换主板后,网卡识别失败的处理方法
1)现象说明公司IDC机房里的一台线上服务器硬件报警,最后排查发现服务器主板坏了,随即联系厂商进行更换主板,最后更换后,登录服务器,发现网卡绑定及ip信息都在,但是ip却ping不通了,进一步排查,重 ...