Luogu3147 USACO16OPEN 262144(动态规划)

  感觉上这个题是可以直接暴力的,每次根据一段连续最小值个数的奇偶性决定是否划分区间,递归处理。然而写起来实在太麻烦了。

  设f[i][j]为以i为左端点合并出j时的右端点。则有f[i][j]=f[f[i][j-1]+1][j-1]。类似于区间dp。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 300000
int n,a[N],f[N][60],ans;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    memset(f,255,sizeof(f));
    for (int i=1;i<=n;i++) f[i][a[i]]=i;
    for (int j=1;j<60;j++)
        for (int i=1;i<=n;i++)
        if (~(f[i][j]=f[f[i][j-1]+1][j-1]==-1?f[i][j]:f[f[i][j-1]+1][j-1])) ans=j;
    cout<<ans;
    return 0;
}

 

posted @ 2018-10-11 18:49  Gloid  阅读(161)  评论(0编辑  收藏  举报