记录编号 483676 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2015]品酒大会 最终得分 100
用户昵称 GravatarHzoi_moyi 是否通过 通过
代码语言 C++ 运行时间 2.815 s
提交时间 2018-01-18 17:49:42 内存使用 127.63 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int sj=300010;
int n,m,a[sj],tx[sj],ty[sj],rk[sj],sa[sj],h[sj],a1,a2,fa[sj];
ll vl[sj],ans1[sj],ans2[sj],sum,ans,tp1,tp2,tp,tp3,tp4,qwq,mx[sj],mi[sj],num[sj];
char s[sj];
struct ls
{
    int num,val;
}ss[sj];
struct tree
{
    int lc,rc,sum;
}t[sj*30];
int comp(const ls&x,const ls&y)
{
	return x.val<y.val;
}
void rsort()
{
	memset(tx,0,sizeof(int)*(m+1));
    for(int i=1;i<=n;i++)  tx[rk[ty[i]]]++;
    for(int i=1;i<=m;i++)  tx[i]+=tx[i-1];
    for(int i=n;i>=1;i--)  sa[tx[rk[ty[i]]]--]=ty[i];
}
void suffix()
{
	int i,j,k,l,p;
	for(i=1;i<=n;i++)  rk[i]=a[i],ty[i]=i;
	m=26;rsort();
	for(p=1,l=1;p<n;m=p,l<<=1)
	{
	    for(p=0,i=n-l+1;i<=n;i++)  ty[++p]=i;
	    for(i=1;i<=n;i++)  if(sa[i]>l)  ty[++p]=sa[i]-l;
	    rsort(),swap(ty,rk),rk[sa[1]]=p=1;
	    for(i=2;i<=n;i++) 
	        rk[sa[i]]=(ty[sa[i]]==ty[sa[i-1]]&&ty[sa[i]+l]==ty[sa[i-1]+l])?p:++p;
	}
	for(i=1,k=0;i<=n;h[rk[i++]]=k)
	    for(k=k?k-1:k,j=sa[rk[i]-1];a[i+k]==a[j+k];k++);
} 
void init()
{
	scanf("%d%s",&n,s);
	memset(fa,-1,sizeof(fa));
	tp1=-1ll<<62,tp2=-1ll<<62,tp3=1ll<<62,tp4=1ll<<62;
    for(int i=1;i<=n;i++)  
	{    
		scanf("%lld",&vl[i]);
        a[i]=s[i-1]-'a'+1;
        if(vl[i]>=tp1)  tp2=tp1,tp1=vl[i];  
        else if(vl[i]>tp2)  tp2=vl[i];
        if(vl[i]<=tp3)  tp4=tp3,tp3=vl[i];
		else if(vl[i]<tp4)  tp4=vl[i];  
	}
}
int find(int x)
{
    if(fa[x]==-1)  return x;
    return fa[x]=find(fa[x]);
}
inline ll maxx(ll x,ll y)
{
	return x>y?x:y;
}
inline ll minn(ll x,ll y)
{
    return x<y?x:y;
}
int main()
{
	freopen("savour.in","r",stdin);
	freopen("savour.out","w",stdout);
    init();
	suffix();
	for(int i=1;i<=n;i++)
	{
	    ss[i].num=i,ss[i].val=h[i];
        num[i]=1,mx[i]=mi[i]=vl[sa[i]];
	}
	sort(ss+1,ss+n+1,comp);
	ans=-1ll<<62;
	for(int i=n;i>=1;i--)
	{
		if(ss[i].val!=ss[i+1].val)  
		    ans1[ss[i+1].val]=sum/2,ans2[ss[i+1].val]=ans;
		a1=ss[i].num,a2=a1-1;
		if(!h[a1])  break;
		a1=find(a1),a2=find(a2);
		sum-=(ll)num[a1]*(num[a1]-1);
	    sum-=(ll)num[a2]*(num[a2]-1);
	    tp=mx[a1]*mx[a2],qwq=mi[a1]*mi[a2];
	    if(tp>ans)   ans=tp;
	    if(qwq>ans)  ans=qwq;
	    if(num[a1]<num[a2])  swap(a1,a2);
	    mx[a1]=maxx(mx[a1],mx[a2]);
	    mi[a1]=minn(mi[a1],mi[a2]);
	    num[a1]+=num[a2];
	    fa[a2]=a1;
	    sum+=(ll)num[a1]*(num[a1]-1);
	}
	ans1[0]=(ll)n*(n-1)/2,ans2[0]=maxx(tp1*tp2,tp3*tp4);
	for(int i=0;i<n;i++)
	    printf("%lld %lld\n",ans1[i],ans2[i]);
	return 0;
}