BZOJ

洛谷

后缀自动机做法

洛谷上SAM比SA慢...BZOJ SAM却能快近一倍...

显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了。

对于相同子串,我们能想到对后缀求height,也就是用 后缀数组+单调栈 维护一段\(height\)相同的区间,单调栈中的\(height\)递增,顺便维护区间最小值(有负数)、最大值、元素个数。

(然后我就不会写了...)

每次弹出区间时,计算该区间右端点和后面的点与该区间内的点的答案(该区间内的点作为右端点的答案已经在它被合并,即出栈时统计过了)。

具体看代码吧...感觉有点神...

//17520kb	4980ms
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=3e5+5; int A[N];
LL sum[N],Ans[N];
//char OUT[7000000],*O=OUT;//5e6 isn't enough...
struct Node
{
int ht,mn,mx,s;
}sk[N];
struct Suffix_Array
{
int sa[N],sa2[N],rk[N],tm[N],ht[N];
char s[N];
void Build(const int n)
{
scanf("%s",s+1);
int m=26,*x=rk,*y=sa2;
for(int i=0; i<=m; ++i) tm[i]=0;
for(int i=1; i<=n; ++i) ++tm[x[i]=s[i]-'a'+1];
for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
for(int i=n; i; --i) sa[tm[x[i]]--]=i;
for(int k=1,p=0; k<n; k<<=1,m=p,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) tm[i]=0;
for(int i=1; i<=n; ++i) ++tm[x[i]];
for(int i=1; i<=m; ++i) tm[i]+=tm[i-1];
for(int i=n; i; --i) sa[tm[x[y[i]]]--]=y[i]; std::swap(x,y), x[sa[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;
}
for(int i=1; i<=n; ++i) rk[sa[i]]=i;
ht[1]=0;
for(int k=0,p,i=1; i<=n; ++i)
{
if(rk[i]==1) continue;
if(k) --k;
p=sa[rk[i]-1];
while(i+k<=n && p+k<=n && s[i+k]==s[p+k]) ++k;
ht[rk[i]]=k;
}
}
}sa; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
//inline void print(LL x)
//{
// static char obuf[20];
// if(x<0) x=-x, *O++='-';
// if(x)
// {
// int t=0; while(x) obuf[++t]=x%10+48, x/=10;
// while(t) *O++=obuf[t--];
// }
// else *O++='0';
//} int main()
{
const int n=read(); sa.Build(n);
for(int i=1; i<=n; ++i) A[i]=read();
memset(Ans,-0x3f,sizeof Ans);
int top=0; sa.ht[n+1]=0;
for(int i=1; i<=n; ++i)
{
int ht=sa.ht[i+1],mx=A[sa.sa[i]],mn=mx,s=1;
while(top && sk[top].ht>=ht)
{
int v=sk[top].ht;
sum[v]+=1ll*s*sk[top].s;
Ans[v]=std::max(Ans[v],std::max(1ll*mx*sk[top].mx,1ll*mn*sk[top].mn));
s+=sk[top].s, mx=std::max(mx,sk[top].mx), mn=std::min(mn,sk[top].mn);
--top;
}
sk[++top]=(Node){ht,mn,mx,s};
}
for(int i=n-1; ~i; --i) sum[i]+=sum[i+1], Ans[i]=std::max(Ans[i],Ans[i+1]);
for(int i=0; i<n; ++i) printf("%lld %lld\n",sum[i],sum[i]?Ans[i]:0);
// for(int i=0; i<n; ++i) print(sum[i]),*O++=' ',print(sum[i]?Ans[i]:0),*O++='\n';
// fwrite(OUT,1,O-OUT,stdout); return 0;
}

BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)的更多相关文章

  1. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  2. BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )

    求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ------------------------- ...

  3. BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)

    BZOJ 洛谷 后缀数组做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 只考虑求极长相同子串,即所有后缀之间的LCP. 而后缀的LCP在后缀树的LCA处.同差异这道题,在每个点处 ...

  4. bzoj 4199: [Noi2015]品酒大会 后缀树

    题目大意: 给定一个长为n的字符串,每个下标有一个权\(w_i\),定义下标\(i,j\)是r相似的仅当\(r \leq LCP(suf(i),suf(j))\)且这个相似的权为\(w_i,w_j\) ...

  5. uoj 131/bzoj 4199 [NOI2015]品酒大会 后缀树+树d

    题目大意 见uoj131 分析 题目的提示还是很明显的 \(r\)相似就就代表了\(0...r-1\)相似 建出后缀树我们能dfs算出答案 再后缀和更新一下即可 注意 细节挺多的,但数据很良心 不然我 ...

  6. BZOJ 4199: [Noi2015]品酒大会 后缀自动机_逆序更新

    一道裸题,可以考虑自底向上去更新方案数与最大值. 没啥难的 细节........ Code: #include <cstdio> #include <algorithm> #i ...

  7. [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集

    [UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...

  8. 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集

    [BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...

  9. [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并

    [NOI2015] 品酒大会 Description 对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值. So ...

随机推荐

  1. HTML&javaSkcript&CSS&jQuery&ajax(三)

    一.HTML块元素 1.块级元素 Block level element ,内联元素 inline element , HTML<div>元素属于块级元素,他是组合其他HTML元素的容器, ...

  2. nginx+tomcat实现集群,redis实现session共享,软连接实现文件共享:http://blog.csdn.net/hua1586981/article/details/78132710

    转载 2017年02月08日 16:52:41 730 相信很多人都听过nginx,这个小巧的东西慢慢地在吞食apache和IIS的份额.那究竟它有什么作用呢?可能很多人未必了解. 说到反向代理,可能 ...

  3. Jmeter 自动化测试报告扩展

    首先了解下生成测试报告的过程,我们看到的测试报告是由.jtl格式转换为.html,html报告的样式由extras目录下xsl文件决定.优化测试报告需要分为两部分内容,首先我们要优化输出的测试内容,其 ...

  4. jenkins原理

      原理:Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 直白的说:这个jenkins是CI ...

  5. WCF+Autofac 实现构造函数依赖注入

    1.新建一个项目 2.要对WCF服务实现Autofac注入,需要实现2个接口,IInstanceProvider与IServiceBehavior,并让实现IServiceBehavior的类成为一个 ...

  6. python---自己实现二分法列表查找

    这是以我自己的思维来实现的,没有用递归. # coding = utf-8 # 二分查找,适用于有序列表,日常编程用不到,因为index函数可以搞定的. # 查找到数字,返回列表中的下标,找不到数字, ...

  7. JDK8 新特性流式数据处理

    https://blog.csdn.net/canot/article/details/52957262

  8. asp.net mvc自动压缩文件,并生成CDN引用

    很多站点都是用了静态文件分离.我推荐一种处理静态文件分离的方式. BundleExtensions.cs public static class BundleExtensions { public s ...

  9. 设备arduino的编译目录

    1.arduino-0023\lib\preferences.txt 修改 #build.path=build build.path=d:\build_wpadk d:\build_wpadk为自定义 ...

  10. Docker镜像、容器剖析

    我们通常所说的docker是什么? 在这里英文本意为“搬运工”这里指的的docker搬运点的是集装箱,集装箱装的是够任意类型的APP,开发者通过Docker可以将app变成一种标准化,可移植的.自管理 ...