Description
一年一度的“幻影阁夏日品酒大会”隆重开幕了。大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品
酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加。在大会的晚餐上,调酒师Rainbow调制了 n 杯鸡尾酒。 这 n
杯鸡尾酒排成一行,其中第 i 杯酒 (1≤i≤n) 被贴上了一个标签 s_i ,每个标签都是 26 个小写英文字母 之一。设
Str(l,r) 表示第 l 杯酒到第 r 杯酒的 r-l+1 个标签顺次连接构成的字符串。若 Str(p,po)=Str(q,qo )
,其中 1≤p≤po≤n,1≤q≤qo≤n,p≠q,po-p+1=qo-q+1=r ,则称第 p 杯酒与第 q 杯酒是“ r 相似”的。当
然两杯“ r 相似”(r>1)的酒同时也是“ 1 相似”、“ 2 相似”、……、“ (r-1) 相似”的。在品尝环节上,
品酒师Freda轻松地评定了每一杯酒的美味度,凭借其专业的水准和经验成功夺取了“首席品酒家”的称号,其中 第 i 杯酒 (1≤i≤n)
的美味度为 a_i 。现在Rainbow公布了挑战环节的问题:本次大会调制的鸡尾酒有一个特点 ,如果把第 p 杯酒与第 q
杯酒调兑在一起,将得到一杯美味度为 a_p a_q 的酒。现在请各位品酒师分别对于 r= 0,1,2,?,n-1
,统计出有多少种方法可以选出 2 杯“ r 相似”的酒,并回答选择 2 杯“ r 相似”的酒调兑可以 得到的美味度的最大值。
Input
输入文件的第1行包含1个正整数 n ,表示鸡尾酒的杯数。 第 2 行包含一个长度为 n 的字符串 S ,其中第 i 个字符表示第 i
杯酒的标签。 第 3 行包含 n 个整数,相邻整数之间用单个空格隔开,其中第 i 个整数表示第 i 杯酒的美味度 a_i 。
n=300,000 |a_i |≤1,000,000,000
Output
输出文件包括 n 行。第 i 行输出 2 个整数,中间用单个空格隔开。
第 1 个整数表示选出两杯“ (i-1)” ” 相似”的酒的方案数, 第 2 个整数表示选出两杯“ (i-1)
相似”的酒调兑可以得到的最大美味度。 若不存在两杯“ (i-1) 相似”的酒,这两个数均为 0 。
Sample Input
10
ponoiiipoi
2 1 4 7 4 8 3 6 4 7
Sample Output
45 56
10 56
3 32
0 0
0 0
0 0
0 0
0 0
0 0
0 0
HINT
【样例说明1】
用二元组 (p,q) 表示第 p 杯酒与第 q 杯酒。
0 相似:所有 45 对二元组都是 0 相似的,美味度最大的是 8×7=56 。
1 相似: (1,8) (2,4) (2,9) (4,9) (5,6) (5,7) (5,10) (6,7) (6,10) (7,10)
,最大的 8×7=56 。2 相似: (1,8) (4,9) (5,6) ,最大的 4×8=32 。
没有 3,4,5,?,9 相似的两杯酒,故均输出 0 。
题解
不让 log2 l o g 2 的SA过的题都不是好题哼
很显然是求任意两个后缀的最长公共前缀
先把SA和height跑出来
倒着离线
任意两个后缀的最长公共前缀就是他们连续一段的height的最小值
枚举答案,每次把height>=枚举的数的位置标为true,如果连成一段了就可以更新答案呀。
维护一个最大次大和最小次小。因为数可能是负数
并查集优化就过了…
哼不让 log2 l o g 2 过的人就是坏淫
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define inf (1<<30)
#define LL long long
#define ULL unsigned long long
#define HA 569
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void write(LL x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
inline void print(LL x){write(x);putchar(' ');}
struct node
{
LL g1,g2;
node(){}
node(LL _g1,LL _g2){g1=_g1;g2=_g2;}
friend bool operator <(node n1,node n2){return n1.g1*n1.g2<n2.g1*n2.g2;}
};
struct gggg
{
LL g1,g2;
gggg(){}
gggg(LL _g1,LL _g2){g1=_g1;g2=_g2;}
friend bool operator <(gggg n1,gggg n2){return n1.g1*n1.g2<n2.g1*n2.g2;}
};
priority_queue<node> heap;
priority_queue<gggg> pppp;
vector<int> li[300005];
LL a1[300005],a2[300005];
char ch[300005];
ULL hash[300005],pre[300005];
int p[300005],height[300005],a[300005],tmp[300005],n;
int Rsort[300005],Rank[300005],sa1[300005],sa2[300005];
int tt[300005];
void get_sa(int len,int m)
{
memcpy(Rank,tmp,sizeof(Rank));
memset(Rsort,0,sizeof(Rsort));
for(int i=1;i<=len;i++)Rsort[Rank[i]]++;
for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1];
for(int i=len;i>=1;i--)sa1[Rsort[Rank[i]]--]=i;
int ln=1,p=0;
while(p<len)
{
int k=0;
for(int i=len-ln+1;i<=len;i++)sa2[++k]=i;
for(int i=1;i<=len;i++)if(sa1[i]-ln>0)sa2[++k]=sa1[i]-ln;
memset(Rsort,0,sizeof(Rsort));
for(int i=1;i<=len;i++)Rsort[Rank[i]]++;
for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1];
for(int i=len;i>=1;i--)sa1[Rsort[Rank[sa2[i]]]--]=sa2[i];
memcpy(tt,Rank,sizeof(tt));
Rank[sa1[1]]=1;p=1;
for(int i=2;i<=len;i++)
{
if(tt[sa1[i]]!=tt[sa1[i-1]] || tt[sa1[i]+ln]!=tt[sa1[i-1]+ln])p++;
Rank[sa1[i]]=p;
}
ln*=2;m=p;
}
}
/*inline bool check(int u,int v,int ln)
{
ULL gg=pre[ln];
return hash[u+ln-1]-hash[u-1]*gg==hash[v+ln-1]-hash[v-1]*gg;
}
inline bool cmp(int n1,int n2)
{
int l=1,r=n,ret=0;//二分长度
while(l<=r)
{
int mid=(l+r)/2;
if(mid>min(n-n1+1,n-n2+1))r=mid-1;
if(!check(n1,n2,mid))r=mid-1;
else ret=mid,l=mid+1;
}
return ch[n1+ret]-'a'<ch[n2+ret]-'a';
}*/
inline void gethe()
{
int j,k=0;
for(int i=1;i<=n;i++)
{
j=p[Rank[i]-1];
if(k)k--;
while(ch[i+k]==ch[j+k])k++;
height[Rank[i]]=k;
}
}
bool v[300005];
int fa[300005],tot[300005],mx[300005][2],mn[300005][2],gg[5];
int findfa(int x){return fa[x]==x?fa[x]:fa[x]=findfa(fa[x]);}
inline void meg(int u,int v)
{
fa[u]=v;tot[v]+=tot[u];
gg[1]=mx[u][0],gg[2]=mx[u][1],gg[3]=mx[v][0],gg[4]=mx[v][1];sort(gg+1,gg+1+4);
mx[v][0]=gg[4];mx[v][1]=gg[3];
gg[1]=mn[u][0],gg[2]=mn[u][1],gg[3]=mn[v][0],gg[4]=mn[v][1];sort(gg+1,gg+1+4);
mn[v][0]=gg[1];mn[v][1]=gg[2];
}
LL aaa;
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
n=read();
scanf("%s",ch+1);
/* pre[0]=1;
for(int i=1;i<=n;i++)
{
hash[i]=hash[i-1]*HA+ch[i]-'a';
pre[i]=pre[i-1]*HA;p[i]=i;
}
sort(p+1,p+1+n,cmp);*/
for(int i=1;i<=n;i++)tmp[i]=ch[i]-'a'+1;
get_sa(n,30);
for(int i=1;i<=n;i++)p[i]=sa1[i],Rank[p[i]]=i;
for(int i=1;i<=n;i++)a[i]=read();
gethe();memset(v,false,sizeof(v));
/* for(int i=1;i<=n;i++)
{
for(int j=p[i];j<=n;j++)printf("%c",ch[j]);
puts("");
printf(" HEIGHT : %d\n",height[i]);
}*/
for(int i=1;i<=n;i++)li[height[i]].push_back(i),fa[i]=i,tot[i]=1,mx[i][0]=mn[i][0]=a[p[i]],mx[i][1]=-inf,mn[i][1]=inf;
LL sum=0;aaa=-(1LL<<63-1);
for(int i=n-1;i>=0;i--)
{
for(int j=0;j<li[i].size();j++)
{
int po=li[i][j];v[po]=true;sum++;
if(po==1)sum--;
if(v[po-1])
{
int pp=findfa(po),q=findfa(po-1);
if(tot[q]!=po-1)sum+=((LL)tot[pp]*(tot[q]+1)-tot[pp]);
else sum+=((LL)tot[pp]*tot[q]-tot[pp]);
int la=tot[q];
meg(pp,q);
/* heap.push(node(mx[q][0],max(mx[q][1],a[p[po-1-la]])));
pppp.push(gggg(mn[q][0],min(mn[q][1],a[p[po-1-la]])));*/
aaa=max(aaa,max((LL)mx[q][0]*max(mx[q][1],a[p[po-1-la]]),(LL)mn[q][0]*min(mn[q][1],a[p[po-1-la]])));
}
if(v[po+1])
{
int pp=findfa(po),q=findfa(po+1);
if(tot[pp]!=po)sum+=((LL)(tot[pp]+1)*tot[q]-tot[q]);
else sum+=((LL)tot[pp]*tot[q]-tot[q]);
int la=tot[pp];
meg(pp,q);
/*heap.push(node(mx[q][0],max(mx[q][1],a[p[po-la]])));
pppp.push(gggg(mn[q][0],min(mn[q][1],a[p[po-la]])));*/
aaa=max(aaa,max((LL)mx[q][0]*max(mx[q][1],a[p[po-la]]),(LL)mn[q][0]*min(mn[q][1],a[p[po-la]])));
}
if(!v[po-1]&&!v[po+1])
{
/*heap.push(node(mx[po][0],max(a[p[po-1]],mx[po][1])));
pppp.push(gggg(mn[po][0],min(mn[po][1],a[p[po-1]])));*/
aaa=max(aaa,max((LL)mx[po][0]*max(mx[po][1],a[p[po-1]]),(LL)mn[po][0]*min(mn[po][1],a[p[po-1]])));
}
}
a1[i]=sum;
if(aaa!=-(1LL<<63-1))a2[i]=aaa;
}
for(int i=0;i<n;i++)
{
print(a1[i]);print(a2[i]);
puts("");
//printf("%lld %lld\n",a1[i],a2[i]);
}
return 0;
}