他要求的就是lcp(x,y)>=i的(x,y)的个数和a[x]*a[y]的最大值

做一下后缀和,就只要求lcp=i的了

既然lcp(x,y)=min(h[rank[x]+1],..,[h[rank[y]]])

那么我们求出来对于每一个h,以它作为最小值的区间的左右端点就可以了,这个可以用单调栈,具体做法见Neat Tree(?哪里具体了)

假设L是i左面第一个h小于等于它的,R是i右面第一个小于它的(一定要一边有=一边没有,很关键)

那就相当于lcp(x,y)=h[i] ,rank[x]∈[L,i-1],rank[y]∈[i,R-1]

数量就是这两个区间大小乘一下,最大值是max(最大值之积,最小值之积)(因为会有负的),这个可以用ST表来做

貌似并查集也能做 但我哪会啊

写的这么辣鸡 开着O2才勉强水过洛谷 哪敢到bzoj去交啊

upd:(Time Limit: 10 Sec)

 #include<bits/stdc++.h>
#define pa pair<ll,ll>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=3e5+;
const ll inf=1e18; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M,deli[maxn],sa[maxn<<],rnk[maxn<<],rnk1[maxn<<],tmp[maxn<<],h[maxn<<],cnt[maxn];
ll ans2[maxn],ma[maxn][],mn[maxn][],dt[maxn];
int stk[maxn],sh,rg[maxn];
char s[maxn]; inline void setsa(){
int i,j=,k;
for(i=;i<=N;i++) cnt[s[i]]=;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) rnk[i]=cnt[s[i]];
for(k=;j!=N;k<<=){
// printf("%d %d %d\n",M,k,j);
CLR(cnt,);
for(i=;i<=N;i++) cnt[rnk[i+k]]++;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) tmp[cnt[rnk[i+k]]--]=i;
CLR(cnt,);
for(i=;i<=N;i++) cnt[rnk[i]]++;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) sa[cnt[rnk[tmp[i]]]--]=tmp[i];
memcpy(rnk1,rnk,sizeof(rnk));
i=;rnk[sa[]]=j=;
for(;i<=N;i++){
if(rnk1[sa[i]]!=rnk1[sa[i-]]||rnk1[sa[i]+k]!=rnk1[sa[i-]+k]) j++;
rnk[sa[i]]=j;
}M=j;
}
for(i=;i<=N;i++)
sa[rnk[i]]=i;
}
inline void seth(){
for(int i=,j=;i<=N;i++){
if(rnk[i]==) continue;
if(j) j--;
int x=sa[rnk[i]-];
while(i+j<=N&&x+j<=N&&s[i+j]==s[x+j]) j++;
h[rnk[i]]=j;
}
} inline void setma(){
for(int i=N;i;i--){
ma[i][]=mn[i][]=deli[sa[i]];
for(int j=;i+(<<j)-<=N;j++){
int k=i+(<<(j-));
ma[i][j]=max(ma[i][j-],ma[k][j-]);
mn[i][j]=min(mn[i][j-],mn[k][j-]);
}
}
} inline pa getma(int l,int r){
int k=log2(r-l+);
return make_pair(max(ma[l][k],ma[r-(<<k)+][k]),min(mn[l][k],mn[r-(<<k)+][k]));
} void solve(){
for(int i=;i<=N;i++){
while(sh&&h[stk[sh]]>h[i])
rg[stk[sh--]]=i;
stk[++sh]=i;
}while(sh) rg[stk[sh--]]=N+;
for(int i=N;i;i--){
while(sh&&h[stk[sh]]>=h[i]){
int r=rg[stk[sh]]-;
pa x=getma(i,stk[sh]-),y=getma(stk[sh],r);
ans2[h[stk[sh]]]=max(ans2[h[stk[sh]]],max(x.first*y.first,x.second*y.second));
dt[h[stk[sh]]]+=1ll*(stk[sh]-i)*(r-stk[sh]+);
sh--;
}
stk[++sh]=i;
}
} int main(){
// freopen("testdata.in","r",stdin);
// freopen("aa.out","w",stdout);
int i,j,k;
N=rd();
scanf("%s",s+);
for(i=;i<=N;i++)
deli[i]=rd();
M=;setsa();
seth();
setma();
CLR(ans2,-);
solve();
for(i=N-;i>=;i--) dt[i]+=dt[i+],ans2[i]=max(ans2[i],ans2[i+]);
for(i=;i<N;i++)
printf("%lld %lld\n",dt[i],dt[i]?ans2[i]:);
return ;
}

luogu2178/bzoj4199 品酒大会 (SA+单调栈)的更多相关文章

  1. Luogu2178 NOI2015 品酒大会 SA、并查集

    传送门 感觉题目讲的很不清楚-- 题目意思就是给出一个长度为\(n\)的字符串,求对于\(r=0,1,...,n-1\),求出\(LCP(suffix_p,suffix_q) \geq r\)的无序数 ...

  2. Codeforces 802I Fake News (hard) (SA+单调栈) 或 SAM

    原文链接http://www.cnblogs.com/zhouzhendong/p/9026184.html 题目传送门 - Codeforces 802I 题意 求一个串中,所有本质不同子串的出现次 ...

  3. Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)

    原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html 题目传送门 - CF873F 题意 给定长度为 $n$ 的字符串 $s$,以及给定这个字 ...

  4. Codeforces 1073G Yet Another LCP Problem $SA$+单调栈

    题意 给出一个字符串\(s\)和\(q\)个询问. 每次询问给出两个长度分别为\(k,l\)的序列\(a\)和序列\(b\). 求\(\sum_{i=1}^{k}\sum_{j=1}^{l}lcp(s ...

  5. BZOJ3238 [Ahoi2013]差异 SA+单调栈

    题面 戳这里 题解 考虑把要求的那个东西拆开算,前面一个东西像想怎么算怎么算,后面那个东西在建出\(height\)数组后相当于是求所有区间\(min\)的和*2,单调栈维护一波即可. #includ ...

  6. poj 3415 Common Substrings【SA+单调栈】

    把两个串中间加一个未出现字符接起来,然后求SA 然后把贡献统计分为两部分,在排序后的后缀里,属于串2的后缀和排在他前面属于串1的后缀的贡献和属于串1的后缀和排在他前面属于串2的后缀的贡献 两部分分别作 ...

  7. [NOI2015]品酒大会(SA数组)

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

  8. 洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)

    补博客! 首先我们观察题目中给的那个求\(ans\)的方法,其实前两项没什么用处,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); ...

  9. 【POJ3415】 Common Substrings (SA+单调栈)

    这道是求长度不小于 k 的公共子串的个数...很不幸,我又TLE了... 解法参考论文以及下面的链接 http://www.cnblogs.com/vongang/archive/2012/11/20 ...

随机推荐

  1. 汇编 STOSB, STOSW, STOSD指令

    知识点: 汇编指令 STOSB STOSW STOSD 一.汇编指令STOSB 004113AC 8DBD B4FEFFFF LEA EDI,DWORD PTR SS:[EBP-14C] 004113 ...

  2. 关于node.js的进程管理

    如果是单纯的运行一个node进程,那会比较简单,例如: node ./example.js 但是一般来说,当我们运行一个node进程之后,我们可能希望对这个进程进行更多的管理,例如,当node程序是一 ...

  3. HBase最佳实践-管好你的操作系统

    本文由  网易云发布. 作者:范欣欣 本篇文章仅限本站分享,如需转载,请联系网易获取授权. 操作系统这个话题其实很早就想拿出来和大家分享,拖到现在一方面是因为对其中各种理论理解并不十分透彻,怕讲不好: ...

  4. js类型----你所不知道的JavaScript系列(5)

    ECMAScirpt 变量有两种不同的数据类型:基本类型,引用类型.也有其他的叫法,比如原始类型和对象类型等. 1.内置类型 JavaScript 有七种内置类型: • 空值(null) • 未定义( ...

  5. 【javascript】详解javaScript的深拷贝

        前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...

  6. kvm虚拟机日常操作命令梳理

    KVM虚拟机的管理主要是通过virsh命令对虚拟机进行管理.废话不多说,下面列出kvm日常管理中的命令 1)查看KVM虚拟机配置文件及运行状态 KVM虚拟机默认配置文件位置: /etc/libvirt ...

  7. jenkins 上命令各种找不到问题

    代码: 兵马未动,粮草先行 作者: 传说中的汽水枪 如有错误,请留言指正,欢迎一起探讨. 转载请注明出处.   在使用jenkins的时候,会使用一些命令行,有的时候明明在电脑的命令行(终端)可以执行 ...

  8. 路由嵌套 active

    http://www.jb51.net/article/102574.htm; https://segmentfault.com/q/1010000008950255 <el-menu :def ...

  9. Flask之WSGI:Werkzeug

    WSGI 一个Web应用的本质就是: 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作为HTTP响应的Body发送给浏览器: 浏览器收到HTTP响应,从HT ...

  10. Linux内核分析第四章读书笔记

    第四章 进程调度 进程调度程序:确保进程能有效工作的一个内核子程序 决定将哪个进程投入运行,何时运行已经运行多长时间 进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统 原则:只 ...