zoukankan      html  css  js  c++  java
  • bzoj4199&uoj131: [Noi2015]品酒大会

    传送门:http://uoj.ac/problem/131

    思路:先求出height,然后根据排名重新给后缀标号,按height从大到小做,每次合并i和i-1,用并查集维护,更新答案。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    const int maxn=300010;
    using namespace std;
    typedef long long ll;
    int n,a[maxn];ll ans[maxn],cnt[maxn];char s[maxn];
    struct orz{int h,pos;}cls[maxn];
    bool cmp(orz a,orz b){return a.h>b.h;}
    
    struct Tufs{
    	int maxs[maxn],mins[maxn],fa[maxn],siz[maxn];
    	int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
    	void merge(int x,int y){
    		x=getfa(x),y=getfa(y),fa[y]=x;
    		maxs[x]=max(maxs[x],maxs[y]);
    		mins[x]=min(mins[x],mins[y]);
    		siz[x]+=siz[y];
    	}
    }ufs;
    
    struct Suffix_Array{
    	int sa[maxn],rank[maxn],t1[maxn],t2[maxn],sum[maxn],h[maxn];
    	void getsa(){
    		int *x=t1,*y=t2,m=255,p=0;
    		for (int i=1;i<=n;i++) sum[x[i]=s[i]]++;
    		for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
    		for (int i=n;i;i--) sa[sum[x[i]]--]=i;
    		for (int j=1;p<n;j<<=1,m=p){
    			p=0;
    			for (int i=n-j+1;i<=n;i++) y[++p]=i;
    			for (int i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j;
    			memset(sum,0,sizeof(sum));
    			for (int i=1;i<=n;i++) sum[x[y[i]]]++;
    			for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
    			for (int i=n;i;i--) sa[sum[x[y[i]]]--]=y[i];
    			swap(x,y),x[sa[1]]=p=1;
    			for (int i=2;i<=n;i++){
    				if (y[sa[i]]!=y[sa[i-1]]||y[sa[i]+j]!=y[sa[i-1]+j]) p++;
    				x[sa[i]]=p;
    			}
    		}
    		
    		memcpy(rank,x,sizeof(rank));
    	}
    	void geth(){
    		for (int i=1,j=0;i<=n;i++){
    			if (rank[i]==1) continue;
    			while (s[i+j]==s[sa[rank[i]-1]+j]) j++;
    			h[rank[i]]=j;
    			if (j) j--;
    		}
    	}
    	void work(){
    		memset(ans,128,sizeof(ans));
    		for (int i=2;i<=n;i++) cls[i-1]=(orz){h[i],i};
    		sort(cls+1,cls+n,cmp);
    		for (int i=cls[1].h,j=1;i>=0;i--){
    			ans[i]=ans[i+1],cnt[i]=cnt[i+1];
    			for (;j<n&&cls[j].h==i;j++){
    				int x=ufs.getfa(cls[j].pos),y=ufs.getfa(cls[j].pos-1);
    				ans[i]=max(ans[i],1ll*ufs.maxs[x]*ufs.maxs[y]);
    				ans[i]=max(ans[i],1ll*ufs.mins[x]*ufs.mins[y]);
    				cnt[i]+=1ll*ufs.siz[x]*ufs.siz[y];
    				ufs.merge(x,y);
    			}
    		}
    		for (int i=0;i<n;i++)
    			if (cnt[i]) printf("%lld %lld
    ",cnt[i],ans[i]);
    			else puts("0 0");
    	}
    }SA;
    
    int main(){
    	scanf("%d%s",&n,s+1);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	SA.getsa(),SA.geth();
    	for (int i=1;i<=n;i++) ufs.fa[i]=i,ufs.mins[SA.rank[i]]=ufs.maxs[SA.rank[i]]=a[i],ufs.siz[i]=1;
    	SA.work();
    	return 0;
    }


  • 相关阅读:
    .net 中文显示乱码问题(Chinese display with messy code)
    Compare the value of entity field.
    人见人爱A^B 题解
    人见人爱A-B 题解
    全局变量
    第39级台阶 题解
    马虎的算式 题解
    做题技巧
    inline用法
    queue函数用法
  • 原文地址:https://www.cnblogs.com/thythy/p/5493533.html
Copyright © 2011-2022 走看看