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

    先放个传送门

    后缀数组模板题

    如果(p,q)(r)相似的,相当于(p,q)有一个长度为(r)(lcp)
    考虑把(SA)(Height)建出来之后,让(Height)从大到小排序.然后从大到小做(因为两杯(r)相似的酒肯定是(0,1,2...r)相似的).用并查集维护每个连通块的(size,max,min).如果要合并(p,q),那么方案加上(size[p]*size[q]),(Ans=max(Ans,Max[p]*Max[q],Min[p]*Min[q]))即可.
    于是我们可以在(O(nlog n))的优秀复杂度内完成此题.

    代码如下(人傻自带大常数)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #define N (1000010)
    #define inf (0x7f7f7f7f)
    #define rg register int
    #define Label puts("NAIVE")
    #define spa print(' ')
    #define ent print('
    ')
    #define rand() (((rand())<<(15))^(rand()))
    typedef long double ld;
    typedef long long LL;
    typedef unsigned long long ull;
    using namespace std;
    struct Union{int x,y,pos;}a[N],b[N],c[N];
    struct edge{int l,r,v;}e[N];
    char s[N]; bool flag; LL ans,cnt,outa[N],outc[N];
    int n,suffix[N],rk[N],sa[N],rec[N],Height[N],M,w[N];
    int mx[N],siz[N],fa[N],mn[N];
    bool cmp(edge A,edge B){return A.v>B.v;}
    void jipai(){
        memset(rec,0,sizeof(rec));
        for(int i=1;i<=n;i++)rec[a[i].y]++;
        for(int i=1;i<=M;i++)rec[i]=rec[i-1]+rec[i];
        for(int i=n;i;i--)b[rec[a[i].y]]=a[i],rec[a[i].y]--;
        memset(rec,0,sizeof(rec));
        for(int i=1;i<=n;i++)rec[b[i].x]++;
        for(int i=1;i<=M;i++)rec[i]=rec[i-1]+rec[i];
        for(int i=n;i;i--)c[rec[b[i].x]]=b[i],rec[b[i].x]--;
        int p=0;
        for(int i=1;i<=n;i++){
            if(c[i].x!=c[i-1].x||c[i].y!=c[i-1].y)p++;
            rk[c[i].pos]=a[c[i].pos].x=p;
            if(p==n)flag=1; M=max(M,p);
        }
    }
    void get_sa(){
        scanf("%d%s",&n,s+1),M=127;
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        for(int i=1;i<=n;i++)
        a[i].x=s[i]-'0'+1,a[i].y=0,a[i].pos=i;
        jipai();
        for(int i=1;i<=n;i++)a[i].x=rk[i];
        for(int k=1;k<=n;k*=2){
            for(int i=1;i<=n;i++)
            if(i+k>n)a[i].y=0;else a[i].y=rk[i+k];
            jipai();
            if(flag)break;
        }
        for(int i=1;i<=n;i++)sa[rk[i]]=i;
    }
    void get_height(){
        int x,y=0;
        for(int i=1;i<=n;Height[rk[i++]]=y)
        for(y=y?y-1:y,x=sa[rk[i]-1];s[i+y]==s[x+y];y++);
    }
    int ask(int x){
        return (fa[x]==x)?x:(fa[x]=ask(fa[x]));
    }
    void unite(int x,int y){
        int p=ask(x),q=ask(y);
        fa[q]=p,cnt+=((LL)siz[p]*(LL)siz[q]);
        ans=max(ans,max((LL)mx[p]*(LL)mx[q],(LL)mn[p]*(LL)mn[q]));
        mx[p]=max(mx[p],mx[q]),mn[p]=min(mn[p],mn[q]),siz[p]+=siz[q];
    }
    int main(){
        get_sa(),get_height();
        for(int i=1;i<=n;i++)fa[i]=i,mx[i]=mn[i]=w[i],siz[i]=1;
        for(int i=2;i<=n;i++)e[i-1]=(edge){sa[i-1],sa[i],Height[i]};
        sort(e+1,e+n,cmp),ans=-1e18-1;
        for(int i=n-1,j=1;i>=0;i--){
            for(;e[j].v==i;j++)unite(e[j].l,e[j].r);
            outa[i]=(cnt>0)?ans:0,outc[i]=cnt;
        }
        for(int i=0;i<n;i++)
        printf("%lld %lld
    ",outc[i],outa[i]);
    }
    
  • 相关阅读:
    陶瓷电容的结构、工艺、失效模式
    Vue.js最佳实践
    Vue 超快速学习
    CSS 小技巧
    HTML5 Canvas
    webkit下面的CSS设置滚动条
    Some untracked working tree files would be overwritten by checkout. Please move or remove them before you can checkout. View them
    JSCS: Please specify path to 'JSCS' package
    React中ref的使用方法
    React 60S倒计时
  • 原文地址:https://www.cnblogs.com/Romeolong/p/10056786.html
Copyright © 2011-2022 走看看