luogu2178/bzoj4199 品酒大会 (SA+单调栈)
他要求的就是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+单调栈)的更多相关文章
- Luogu2178 NOI2015 品酒大会 SA、并查集
传送门 感觉题目讲的很不清楚-- 题目意思就是给出一个长度为\(n\)的字符串,求对于\(r=0,1,...,n-1\),求出\(LCP(suffix_p,suffix_q) \geq r\)的无序数 ...
- Codeforces 802I Fake News (hard) (SA+单调栈) 或 SAM
原文链接http://www.cnblogs.com/zhouzhendong/p/9026184.html 题目传送门 - Codeforces 802I 题意 求一个串中,所有本质不同子串的出现次 ...
- Codeforces 873F Forbidden Indices 字符串 SAM/(SA+单调栈)
原文链接https://www.cnblogs.com/zhouzhendong/p/9256033.html 题目传送门 - CF873F 题意 给定长度为 $n$ 的字符串 $s$,以及给定这个字 ...
- Codeforces 1073G Yet Another LCP Problem $SA$+单调栈
题意 给出一个字符串\(s\)和\(q\)个询问. 每次询问给出两个长度分别为\(k,l\)的序列\(a\)和序列\(b\). 求\(\sum_{i=1}^{k}\sum_{j=1}^{l}lcp(s ...
- BZOJ3238 [Ahoi2013]差异 SA+单调栈
题面 戳这里 题解 考虑把要求的那个东西拆开算,前面一个东西像想怎么算怎么算,后面那个东西在建出\(height\)数组后相当于是求所有区间\(min\)的和*2,单调栈维护一波即可. #includ ...
- poj 3415 Common Substrings【SA+单调栈】
把两个串中间加一个未出现字符接起来,然后求SA 然后把贡献统计分为两部分,在排序后的后缀里,属于串2的后缀和排在他前面属于串1的后缀的贡献和属于串1的后缀和排在他前面属于串2的后缀的贡献 两部分分别作 ...
- [NOI2015]品酒大会(SA数组)
[NOI2015]品酒大会 题目描述 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发"首席品酒家"和" ...
- 洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)
补博客! 首先我们观察题目中给的那个求\(ans\)的方法,其实前两项没什么用处,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); ...
- 【POJ3415】 Common Substrings (SA+单调栈)
这道是求长度不小于 k 的公共子串的个数...很不幸,我又TLE了... 解法参考论文以及下面的链接 http://www.cnblogs.com/vongang/archive/2012/11/20 ...
随机推荐
- CF 859E Desk Disorder
题目大意:一个经典的游戏:抢椅子.有\(n\)个人以及\(2n\)把椅子.开始时每个人坐在一把椅子上,而且他们每个人都有一个下一步想坐的位置(可以与之前重合).每一个下一次可以在自己现在做的椅子和想坐 ...
- HNOI2019 爆零记
HNOI2019爆零记 day \(-inf\) ~ day \(0\) 开学一周之后才停的课,停课之后就开始每天被包菜.我三月份几乎没有更博,就是因为每天都被虐的自闭了. day \(0\) 本来是 ...
- Linux下的Mongodb部署应用梳理
一.Mongodb简介 官网地址:http://www.mongodb.org/ MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.MongoDB 是一 ...
- 索引节点(inode)爆满问题处理
关于磁盘空间中索引节点爆满的问题还是挺多的,借此跟大家分享几个情况: 情况一 在公司一台配置较低的Linux服务器(内存.硬盘比较小)的/data分区内创建文件时,系统提示磁盘空间不足,用df -h命 ...
- 20135327郭皓--Linux内核分析第六周 进程的描述和进程的创建
进程的描述和进程的创建 一.进程的描述 操作系统三大功能: 进程管理 内存管理 文件系统 进程描述符task_struct数据结构 task _ struct:为了管理进程,内核必须对每个进程进行清晰 ...
- <<浪潮之巅>>阅读笔记一
第一次的阅读就想读这本书的,却因为很多愿意一直拖到现在,因为听说这本书在李开复先生 的微博上有推荐,更是增加了我的阅读兴趣.可能是因为在网上找的电子版的原因,通篇阅读的速度很快,但是没有纸质数那种细嚼 ...
- 百度AI--自然语言处理之Java开发
参数: public class APIConstants { //设置APPID/AK/SK public static final String APP_ID = "108***&quo ...
- Robot Framework 入门教程总结
Robot Framework 作为一款通用测试框架,可加载多种测试库.驱动多种测试工具,并可对各种自定义脚本进行集成.对于Robot Framework,我准备将其分为 入门--Robot Fram ...
- js拷贝实例;
,]]; // var arr2 =arr1.slice(0); // arr1[0] ="z"; // arr1[2][0] = "v"; // consol ...
- [日常工作]虚拟机或者实体机转换成HyperV虚拟机的方法
1.环境种类比较多, 有vb的 vm的还有人想直接用hyperV的 毕竟docker 是一个趋势, win10 上面 安装了hyperV 启用docker 角色之后 安装vb和vm的话 就没法启用CP ...