【BZOJ1717】&&【POJ3261】[Usaco2006 Dec]Milk Patterns 產奶的模式

1717: [Usaco2006 Dec]Milk Patterns 產奶的模式

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1186  Solved: 640
[Submit][Status][Discuss]

Description

農夫John發現他的奶牛產奶的質量一直在變更。通過細緻的調查,他發現:雖然他不能預見明天產奶的質量,但連續的若干天的質量有不少重疊。咱們稱之爲一個「模式」。 John的牛奶按質量能夠被賦予一個0到1000000之間的數。而且John記錄了N(1<=N<=20000)天的牛奶質量值。他想知道最長的出現了至少K(2<=K<=N)次的模式的長度。好比1 2 3 2 3 2 3 1 中 2 3 2 3出現了兩次。當K=2時,這個長度爲4。php

Input

* Line 1: 兩個整數 N,K。ios

* Lines 2..N+1: 每行一個整數表示當天的質量值。數組

Output

* Line 1: 一個整數:N天中最長的出現了至少K次的模式的長度ide

Sample Input

8 2
1
2
3
2
3
2
3
1

Sample Output

4

HINT

 

Source

Goldspa

列表內某範姓同窗和某尹姓同窗差點坑害我 我就是要先貼單調隊列debug

先聲明 這個題單調隊列絕對是對的 由於他和二分徹底等價 code

單調隊列的話,咱們考慮其向前k-1個數內的最小值(爲何不是k個?由於height數組的定義)blog

答案是最小值內的最大值隊列

而分的話 咱們考慮k-1個height數組內的最小值是否知足 知足便可ip

能夠發現 這兩個條件徹底能夠轉化 由於最小值知足時的最大值必定就是最小值內的最大值

(md其實我這篇文章純粹是發泄一下憤怒,坑了我兩節課進去就爲了驗證這個原本就對的結論,最重要的是我拿一個沒處理0的代碼自信的說我絕對沒錯 mdzz 反正我改完了確定是對的)

順便留組數據警示後人

4 2

1

0

0

0

答案是2

爲了發泄憤怒,我只貼單調隊列的板子,二分的本身腦補一下應該能出來。

/*In Search Of Life*/
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iomanip>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#define debug(x) cerr<<#x<<"="<<x<<endl
#define INF 0x7f7f7f7f
#define llINF 0x7fffffffffffll
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
inline int init()
{
    int now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
inline long long llinit()
{
    long long now=0,ju=1;char c;bool flag=false;
    while(1)
    {
        c=getchar();
        if(c=='-')ju=-1;
        else if(c>='0'&&c<='9')
        {
            now=now*10+c-'0';
            flag=true;
        }
        else if(flag)return now*ju;
    }
}
int n,m,k,sa[1000005],auxsort[1000005],auxval[1000005],rank[1000005],auxa[1000005],auxb[1000005],height[1000005];
int str[1000005];
int getVal(int x[],int pos)
{
    if(pos<=n)return x[pos];
    else return -1;
}
void getsa()
{
    m=1000005;int *x=auxa,*y=auxb,cnt=0;
    for(int i=1;i<=n;i++)auxsort[x[i]=str[i]]++;
    for(int i=1;i<=m;i++)auxsort[i]+=auxsort[i-1];
    for(int i=n;i>=1;i--)sa[auxsort[x[i]]--]=i;
    for(int j=1;cnt<n;j<<=1,m=cnt)
    {
        cnt=0;
        for(int i=n-j+1;i<=n;i++)y[++cnt]=i;
        for(int i=1;i<=n;i++)if(sa[i]>j)y[++cnt]=sa[i]-j;
        for(int i=1;i<=n;i++)auxval[i]=x[y[i]];
        for(int i=0;i<=m;i++)auxsort[i]=0;
        for(int i=1;i<=n;i++)auxsort[auxval[i]]++;
        for(int i=1;i<=m;i++)auxsort[i]+=auxsort[i-1];
        for(int i=n;i>=1;i--)sa[auxsort[auxval[i]]--]=y[i];
        swap(x,y);cnt=x[sa[1]]=1;
        for(int i=2;i<=n;i++)
        {
            if(y[sa[i]]==y[sa[i-1]]&&getVal(y,sa[i]+j)==getVal(y,sa[i-1]+j))x[sa[i]]=cnt;
            else x[sa[i]]=++cnt;
        }
    }
    for(int i=1;i<=n;i++)rank[sa[i]]=i;
    cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(rank[i]==1)continue;
        if(cnt)cnt--;
        int j=sa[rank[i]-1];
        while(getVal(str,i+cnt)==getVal(str,j+cnt))++cnt;
        height[rank[i]]=cnt;
    }
    return;
}
int q[1000005];
int head=1,tail=0;
int minx[1000005];
int ans=0;
int main()
{
    n=init();k=init();
    for(int i=1;i<=n;i++)str[i]=init();
    getsa();
    for(int i=1;i<=n;i++)
    {
        while(tail>=head&&height[q[tail]]>=height[i])
        {
            --tail;
        }
        q[++tail]=i;
        while(tail>=head&&q[tail]-q[head]>=k-1)
        {
            ++head;
        }
        minx[i]=height[q[head]];
        if(i>=k)ans=max(ans,minx[i]);
    }
    printf("%d\n",ans);
    return 0;
}
View Code
相關文章
相關標籤/搜索