zoukankan      html  css  js  c++  java
  • 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集

    【BZOJ4199】[Noi2015]品酒大会

    题面http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144

    题解:听说能用SAM?SA默默水过~

    本题的实现还是非常简单的,先求出height数组,然后两杯酒'r'相似就等价于二者中间的height都>=r,于是我们将height排序,从大到小扔进去,那么所有连续的区间中的点对就都是相似的了。维护连续区间可以用并查集。统计点对个数需要维护size,统计最大乘积需要维护最(次)大(小)值,然后没了~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=300010;
    int n,m;
    typedef long long ll;
    int sa[maxn],st[maxn],ra[maxn],rb[maxn],r[maxn],h[maxn],rank[maxn];
    int f[maxn],q[maxn],v[maxn];
    ll ans[maxn],sum[maxn],m1[maxn],m2[maxn],n1[maxn],n2[maxn],siz[maxn];
    char str[maxn];
    void work()
    {
    	int i,j,p,k,*x=ra,*y=rb;
    	for(i=0;i<n;i++)	st[x[i]=r[i]]++;
    	for(i=1;i<m;i++)	st[i]+=st[i-1];
    	for(i=n-1;i>=0;i--)	sa[--st[x[i]]]=i;
    	for(j=p=1;p<n;j<<=1,m=p)
    	{
    		for(p=0,i=n-j;i<n;i++)	y[p++]=i;
    		for(i=0;i<n;i++)	if(sa[i]>=j)	y[p++]=sa[i]-j;
    		for(i=0;i<m;i++)	st[i]=0;
    		for(i=0;i<n;i++)	st[x[y[i]]]++;
    		for(i=1;i<m;i++)	st[i]+=st[i-1];
    		for(i=n-1;i>=0;i--)	sa[--st[x[y[i]]]]=y[i];
    		for(swap(x,y),x[sa[0]]=0,i=p=1;i<n;i++)
    			x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j])?p-1:p++;
    	}
    	for(i=1;i<n;i++)	rank[sa[i]]=i;
    	for(i=k=0;i<n-1;h[rank[i++]]=k)
    		for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
    }
    int find(int x)
    {
    	return (f[x]==x)?x:(f[x]=find(f[x]));
    }
    bool cmp(int a,int b)
    {
    	return h[a]>h[b];
    }
    int main()
    {
    	scanf("%d%s",&n,str);
    	int i,j,a,b;
    	for(i=0;i<n;i++)	r[i]=str[i]-'a'+1;
    	for(i=0;i<n;i++)	scanf("%d",&v[i]);
    	m=27,n++,work(),n--;
    	for(i=1;i<=n;i++)	q[i]=f[i]=i,m1[i]=n1[i]=v[sa[i]],m2[i]=-1ll<<60,n2[i]=1ll<<60,siz[i]=1;
    	sort(q+2,q+n+1,cmp);
    	ans[n]=-1ll<<60;
    	for(i=2,j=n-1;j>=0;j--)
    	{
    		ans[j]=ans[j+1],sum[j]=sum[j+1];
    		for(;h[q[i]]==j&&i<=n;i++)
    		{
    			a=find(q[i]-1),b=find(q[i]);
    			if(m1[a]>m1[b])	m2[b]=max(m1[b],m2[a]),m1[b]=m1[a];
    			else	m2[b]=max(m2[b],m1[a]);
    			if(n1[a]<n1[b])	n2[b]=min(n1[b],n2[a]),n1[b]=n1[a];
    			else	n2[b]=min(n2[b],n1[a]);
    			ans[j]=max(ans[j],max(n1[b]*n2[b],m1[b]*m2[b]));
    			sum[j]+=siz[a]*siz[b];
    			siz[b]+=siz[a],f[a]=b;
    		}
    	}
    	for(i=0;i<n;i++)	printf("%lld %lld
    ",sum[i],ans[i]==ans[n]?0:ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Codeforces Round 546 (Div. 2)
    Codeforces Round 545 (Div. 2)
    Codeforces Round 544(Div. 3)
    牛客小白月赛12
    Codeforces Round 261(Div. 2)
    Codeforces Round 260(Div. 2)
    Codeforces Round 259(Div. 2)
    Codeforces Round 258(Div. 2)
    Codeforces Round 257 (Div. 2)
    《A First Course in Probability》-chaper5-连续型随机变量-随机变量函数的分布
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6953357.html
Copyright © 2011-2022 走看看