zoukankan      html  css  js  c++  java
  • [USACO5.1] 乐曲主题Musical Themes

    题目链接:戳我

    Emmm......hash怎么做啊不会啊

    这里是SA后缀数组版本的

    就是先两两做差分,作为要处理后缀的数组。普通地求出来h数组之后,我们二分这个答案,然后判定是否合法就行了。是否合法即(min(sa[j])+h[i]<max(sa[j]),j<=i)

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 100010
    using namespace std;
    int n,m,p;
    int a[MAXN],b[MAXN],tp[MAXN],tax[MAXN],rnk[MAXN],sa[MAXN],h[MAXN];
    inline void qsort()
    {
        for(int i=1;i<=m;i++) tax[i]=0; 
        for(int i=1;i<=n;i++) tax[rnk[i]]++;
        for(int i=1;i<=m;i++) tax[i]+=tax[i-1];
        for(int i=n;i>=1;i--) sa[tax[rnk[tp[i]]]--]=tp[i];
    }
    inline void suffix_sort()
    {
        m=MAXN,p=0;
        for(int i=1;i<=n;i++) rnk[i]=b[i],tp[i]=i;
        qsort();
        for(int w=1;p<n;m=p,w<<=1)
        {
            p=0;
            for(int i=1;i<=w;i++) tp[++p]=n+i-w;
            for(int i=1;i<=n;i++) if(sa[i]-w>0) tp[++p]=sa[i]-w;
            qsort();
            swap(rnk,tp);
            p=rnk[sa[1]]=1;
            for(int i=2;i<=n;i++)
                rnk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+w]==tp[sa[i-1]+w])?p:++p;
        }
    }
    inline void get_h()
    {
        int j,k=0;
        for(int i=1;i<=n;i++)
        {
            if(k) k--;
            int j=sa[rnk[i]-1];
            while(b[i+k]==b[j+k]) k++;
            h[rnk[i]]=k;
        }
        // for(int i=1;i<=n;i++) printf("rnk[%d]=%d
    ",i,rnk[i]);
        // for(int i=1;i<=n;i++) printf("h[%d]=%d
    ",i,h[i]);
    }
    inline bool check(int x)
    {
        int minn=n,maxx=0;
        for(int i=2;i<=n;i++)
        {
            if(h[i]>=x) 
                minn=min(minn,min(sa[i],sa[i-1])),maxx=max(maxx,max(sa[i],sa[i-1]));
            if(h[i]<x||i==n)
            {
                if(minn+x<maxx) return true;
                minn=n,maxx=0;
            }
        }
        return false;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        n--;
        for(int i=1;i<=n;i++) b[i]=a[i+1]-a[i]+88;
        // for(int i=1;i<=n;i++) printf("b[%d]=%d
    ",i,b[i]);
        suffix_sort();
        get_h();
        int l=0,r=n,ans;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            // printf("l=%d r=%d mid=%d
    ",l,r,mid);
            if(check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        if(ans<4||ans>(n+1)/2) printf("0
    ");
        else printf("%d
    ",ans+1);
        return 0;
    }
    
  • 相关阅读:
    mysql 统计新增每天数据
    Oracle dg下掉一个从库
    rman全备脚本
    Linux Shell 统计一(行列)数值的总和及行、列转换
    pt工具加字段脚本
    MySQL慢日志切割邮件发送脚本
    MySQL主从复制邮件报警脚本
    读书清单
    数据库学习笔记
    JAVAEE学习笔记
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10742888.html
Copyright © 2011-2022 走看看