他要求的就是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. cp 命令有坑

    cp 是个很常用的命令, 基本语法为  cp -v  a   b  把文件a 复制为文件b(-v为显示做了什么,这是非常安全的做法,建议新手添加此参数) 参数说明: -a:此选项通常在复制目录时使用, ...

  2. 大话重构连载15:采用Mock技术完成测试

    第五次重构我们引入了数据库的设计,用户信息要从数据库中读取,问候语库存储在数据库中,并支持添加与更新.数据库的引入使自动化测试变得困难了,因为数据状态总是变化着的,而这种变化使得测试过程不能复现,这是 ...

  3. python-批量添加图片水印

    前言: 最近总是被无良公众号和培训机构拷贝文章,他们根本不会给你备注原文出处,这种行为真的让人不高兴,所以计划以后的文章都添加上自己的水印. 话不多说,直接上代码. 一.单张图片添加文字水印 # -* ...

  4. Redis常用操作--------SortedSet(有序集合)

    1.ZADD key score member [[score member] [score member] ...] 将一个或多个 member 元素及其 score 值加入到有序集 key 当中. ...

  5. #科委外文文献发现系统——导出word模板1.0

    ps:该篇文档由实验室ljg提供. Crowdsourcing 一.             技术简介 Crowdsourcing, a modern business term coined in ...

  6. github个人心得和链接

    github使用心得: 在本次github使用过程中,我总结了git常用命令,都有哪些功能? git常用命令: git config :配置git git add:更新working director ...

  7. 项目目前展示图 有几个Activity页还没连上不能一次展示出来

  8. css - 背景图片充满整个屏幕

    body { /* 加载背景图 */ background: url("../static/images/index/backImg.jpg") no-repeat; /* 背景图 ...

  9. 2017BUAA软工个人项目之数独生成与求解

    1.项目GitHub地址:https://github.com/ZiJiaW/Soduko (由于一开始把sudoku看成了soduko,于是名字建错了,读起来可能有点奇怪…) 2.项目PSP表格如下 ...

  10. 业务-----修改Service常用逻辑

    注意:修改时唯一属性不能重复 //num==null 时,没有修改Num,不用考虑重复问题.//num!=null 时,修改了num.考虑重复问题 if(!StringUtils.isEmpty(re ...