zoukankan      html  css  js  c++  java
  • bzoj千题计划257:bzoj4199: [Noi2015]品酒大会

    http://www.lydsy.com/JudgeOnline/problem.php?id=4199

    求出后缀数组的height

    从大到小枚举,合并

    维护组内 元素个数,最大、次大、最小、次小

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 300001
    
    char s[N];
    int n,a[N],b[N];
    
    int p,q=1;
    int v[N];
    int sa[2][N],rk[2][N],height[N];
    
    vector<int>V[N];
    
    int fa[N],siz[N];
    long long sum[N],mx[N];
    int mx1[N],mx2[N],mi1[N],mi2[N];
    
    int MX1,MX2,MI1,MI2;
    
    void read (int &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=f;
    }
    
    void mul(int k,int *sa,int *rk,int *SA,int *RK)
    {
        for(int i=1;i<=n;++i) v[rk[sa[i]]]=i;
        for(int i=n;i;--i) if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;    
        for(int i=n-k+1;i<=n;++i) SA[v[rk[i]]--]=i;
        for(int i=1;i<=n;++i) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);
    }
    
    void presa()
    {
        for(int i=1;i<=n;++i) v[a[i]]++;
        for(int i=1;i<=26;++i) v[i]+=v[i-1];
        for(int i=1;i<=n;++i) sa[p][v[a[i]]--]=i;
        for(int i=1;i<=n;++i) rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
        for(int k=1;k<n;k<<=1,swap(p,q)) 
        mul(k,sa[p],rk[p],sa[q],rk[q]);
    }
    
    void get_height()
    {
        int j;
        for(int i=1,k=0;i<=n;++i)
        {
            j=sa[p][rk[p][i]-1];
            while(a[i+k]==a[j+k]) k++;
            height[rk[p][i]]=k;
            if(k) k--;
        }
    }
    
    int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
    
    void unionn(int x,int y,int i)
    {
        x=find(x);
        y=find(y);
        sum[i]+=1LL*siz[x]*siz[y];
        siz[y]+=siz[x];
        if(mx2[x]>=mx1[y])
        {
            mx2[y]=mx2[x];
            mx1[y]=mx1[x];
        }
        else 
        {
            if(mx2[x]>mx2[y]) mx2[y]=mx2[x];
            if(mx1[x]>=mx1[y])
            {
                mx2[y]=mx1[y];
                mx1[y]=mx1[x];
            }
            else if(mx1[x]>mx2[y]) mx2[y]=mx1[x];
        }
        if(mi2[x]<=mi1[y])
        {
            mi2[y]=mi2[x];
            mi1[y]=mi1[x];
        }
        else
        {
            if(mi2[x]<mi2[y]) mi2[y]=mi2[x];
            if(mi1[x]<=mi1[y])
            {
                mi2[y]=mi1[y];
                mi1[y]=mi1[x];
            }
            else if(mi1[x]<mi2[y]) mi2[y]=mi1[x];
        }
        mx[i]=max(mx[i],max(1LL*mx1[y]*mx2[y],1LL*mi1[y]*mi2[y]));
        fa[x]=y;
    }
        
    void solve()
    {
        for(int i=1;i<=n;++i) 
        {
            fa[i]=i;
            siz[i]=1;
            mx[i]=-1e18;
            mx1[i]=b[i];
            mx2[i]=-1e9;
            mi1[i]=b[i];
            mi2[i]=1e9;
        }
        for(int i=2;i<=n;++i) V[height[i]].push_back(i);
        int s,w;
        for(int i=n;i;--i)
        {
            s=V[i].size();
            for(int j=0;j<s;++j)
            {
                w=V[i][j];
                if(find(sa[p][w-1])!=find(sa[p][w])) unionn(sa[p][w-1],sa[p][w],i);
                if(w<n && height[w+1]>=i && find(sa[p][w])!=find(sa[p][w+1])) unionn(sa[p][w+1],sa[p][w],i);
            }
        }
        for(int i=n-1;i;--i)
        {
            sum[i]+=sum[i+1];
            mx[i]=max(mx[i],mx[i+1]);
        }
        cout<<1LL*n*(n-1)/2<<' '<<max(1LL*MX1*MX2,1LL*MI1*MI2)<<'
    ';
        for(int i=1;i<n;++i) 
        {
            cout<<sum[i]<<' ';
            if(!sum[i]) cout<<0<<'
    ';
            else cout<<mx[i]<<'
    ';
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        scanf("%s",s+1);
        for(int i=1;i<=n;++i) a[i]=s[i]-'a'+1;
        MX1=MX2=-1e9;
        MI1=MI2=1e9;
        for(int i=1;i<=n;++i) 
        {
            read(b[i]);
            if(b[i]>=MX1)
            {
                MX2=MX1;
                MX1=b[i];
            }
            else if(b[i]>MX2) MX2=b[i];
            if(b[i]<=MI1) 
            {
                MI2=MI1;
                MI1=b[i];
            }
            else if(b[i]<MI2) MI2=b[i];
        }
        presa();
        get_height();
        solve();
    }
  • 相关阅读:
    杜马岛
    Type interface com.zhaoka.mapper.DatKcardKmMapper is not known to the MapperRegistry
    jsp实现自动登录
    Struts2中的get、set方法重要性 .
    struts2 通过前台标签name属性将值传到后台,没有name属性传值,则后台对象有默认值,不为null。
    Jsp 操作 Cookie 实现自动登录
    struts2的bean类名首字母和第二个字母都不能大写
    mybatis自动生成的ExamMapper.xml方法总结
    Mybatis插入时注意,没有主键值。所以主键一般为自增类型
    <ywaf:code code="${project.projectType}" typeCode="PROJECT_TYPE"/>
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8509906.html
Copyright © 2011-2022 走看看