zoukankan      html  css  js  c++  java
  • uoj131【NOI2015】品酒大会

    题目链接
    很容易想到p和q"r相似"就等价于在后缀数组中q与p之间的height值(ge r),也就是说(<r)的那些height值会把排好序后的后缀分割成若干段,可以想到倒序枚举r,每当r减小1时,中间把他们分开的那些"屏障"就会减少一些,两边的集合会合并到一起,现在的问题就是给定一个集合,支持合并操作,每次询问元素乘积最大值(方案数显然是(C_{siz}^2))。由于有负值,只需记正值中最大的两个与负值中最小的两个即可。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<bitset>
    #define P puts("lala")
    #define cp cerr<<"lala"<<endl
    #define ln putchar('
    ')
    #define pb push_back
    #define fi first
    #define se second
    #define mkp make_pair
    using namespace std;
    inline int read()
    {
        char ch=getchar();int g=1,re=0;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
        return re*g;
    }
    typedef long long ll;
    typedef pair<int,int> pii;
    
    const int N=300050;
    char s[N];
    int n,Rank[N],tt2[N],sa[N],cnt[N],hei[N];
    void buildsa()
    {
    	int i,m=0,*x=Rank,*y=tt2;
    	for(i=1;i<=n;++i) cnt[x[i]=s[i]]++,m=max(x[i],m);
    	for(i=2;i<=m;++i) cnt[i]+=cnt[i-1];
    	for(i=n;i;--i) sa[cnt[x[i]]--]=i;
    	for(int k=1;k<n;k<<=1)
    	{
    		int p=0;
    		for(i=n-k+1;i<=n;++i) y[++p]=i;
    		for(i=1;i<=n;++i) if(sa[i]>k) y[++p]=sa[i]-k;
    		for(i=1;i<=m;++i) cnt[i]=0;
    		for(i=1;i<=n;++i) cnt[x[y[i]]]++;
    		for(i=2;i<=m;++i) cnt[i]+=cnt[i-1];
    		for(i=n;i;--i) sa[cnt[x[y[i]]]--]=y[i];
    		swap(x,y);
    		p=1; x[sa[1]]=1;
    		for(i=2;i<=n;++i) x[sa[i]]=y[sa[i-1]]==y[sa[i]]
    		&&y[sa[i-1]+k>n?0:sa[i-1]+k]==y[sa[i]+k>n?0:sa[i]+k]?p:++p;
    		m=p;
    		if(m>=n) break;
    	}
    	for(i=1;i<=n;++i) Rank[sa[i]]=i;
    }
    void buildheight()
    {
    	int i,k=0;
    	for(i=1;i<=n;++i)
    	{
    		if(k) k--;
    		int j=sa[Rank[i]-1];
    		while(s[i+k]==s[j+k]) k++;
    		hei[Rank[i]]=k;
    	}
    }
    
    struct dsynh
    {
    	vector<int>neg,pos;
    	dsynh() {neg.clear();pos.clear();}
    	inline ll query()
    	{
    		if(neg.size()+pos.size()<=1) return 0;
    		ll ans=-3e18;
    		if(neg.size()==2) ans=max(ans,1ll*neg[0]*neg[1]);
    		if(pos.size()==2) ans=max(ans,1ll*pos[0]*pos[1]);
    		if(neg.size()&&pos.size()) ans=max(ans,1ll*neg[0]*pos[0]);
    		return ans;
    	}
    	inline void push(ll x)
    	{
    		if(x<0) neg.pb(x);
    		else pos.pb(x);
    	}
    }t[N];
    vector<int>ve[N];
    int fa[N],siz[N];
    inline int find(int x)
    {
    	if(fa[x]!=x) return fa[x]=find(fa[x]);
    	return fa[x];
    }
    ll ans1=0;
    ll merge(int x,int y)
    {
    	x=find(x); y=find(y);
    	ans1-=(1ll*siz[x]*(siz[x]-1)/2+1ll*siz[y]*(siz[y]-1)/2);
    	fa[x]=y; siz[y]+=siz[x];
    	ans1+=1ll*siz[y]*(siz[y]-1)/2;
    
    	for(int i=0;i<t[x].neg.size();++i) t[y].push(t[x].neg[i]);
    	for(int i=0;i<t[x].pos.size();++i) t[y].push(t[x].pos[i]);
    	t[x].neg.clear(); t[x].pos.clear();
    
    	sort(t[y].neg.begin(),t[y].neg.end(),greater<int>() );
    	while(t[y].neg.size()>2) t[y].neg.erase(t[y].neg.begin());
    
    	sort(t[y].pos.begin(),t[y].pos.end());
    	while(t[y].pos.size()>2) t[y].pos.erase(t[y].pos.begin());
    	return t[y].query();
    }
    
    int val[N];
    ll out1[N],out2[N];
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    #endif
        int i,j,opt,T;
        n=read();
        scanf("%s",s+1);
        for(i=1;i<=n;++i) val[i]=read();
        buildsa(); buildheight();
    
        for(i=2;i<=n;++i) ve[hei[i]].pb(i);
        for(i=1;i<=n;++i) siz[i]=1,fa[i]=i,t[i].push(val[sa[i]]);
    
        ll ans2=-3e18;
        for(int r=n-1;r>=0;--r)
        {
        	int siz=ve[r].size();
        	for(i=0;i<siz;++i)
        		ans2=max(merge(ve[r][i]-1,ve[r][i]),ans2);
        	out1[r]=ans1; out2[r]=ans2==-3e18?0:ans2;
        }
        for(i=0;i<n;++i) printf("%lld %lld
    ",out1[i],out2[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    c# 泛型集合Dictionary
    int+? int后带问题是什么意思,请看内容。
    在ASP.NET中实现Url ReWriting 示例
    #DataDirectory是什么意思呢?
    vs2008生成自定义dll,VS2008发布、生成网站时设置固定的dll文件名?
    平台安装注意事项
    快速开发平台程序运行环境
    快速开发平台介绍(动态)
    快速开发平台程序安装包20120612
    JavaFx 2.0总结
  • 原文地址:https://www.cnblogs.com/thkkk/p/8341486.html
Copyright © 2011-2022 走看看