比较弱,只写了金组和银组,铂金组的第一题。

 

262144】

http://www.usaco.org/index.php?page=viewproblem2&cpid=648

给一个序列,相邻两个数组相同的可以合并变成数值大一的数,问最大能得到的数。n<262144,val<=40

是金组某道题的升级版。

因为val<40,实际上最大可以取到的不超过60.所以从1-60,看看从i开始是否能合并到当前数值。可以的话记录合并到哪一位。

初始化f[i][val[i]]=i+1,状态转移f[i][j]=f[f[i][j-1][j-1]。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<cmath>
#include<vector>
#include<map>
#define maxn 300000
using namespace std;

int f[62][maxn],num[maxn],ans,n;

void input() {freopen("262144.in","r",stdin);freopen("262144.out","w",stdout);}
void output() {fclose(stdin);fclose(stdout);}
void work()
{
    int i,k;
    memset(f,0,sizeof(f));
    for (k=0;k<=60;k++) {
        for (i=1;i<=n;i++) {
            if (num[i]==k) f[k][i]=i+1;
            else {
                if (!k || !f[k-1][i] || !f[k-1][f[k-1][i]]) f[k][i]=0;
                else f[k][i]=f[k-1][f[k-1][i]];
            }
            if (f[k][i]) ans=k;
        }
        f[k][n+1]=0;
    }
    return;
}

int main()
{
    input();
    scanf("%d\n",&n);
    int i;
    for (i=1;i<=n;i++) scanf("%d",&num[i]);
    work();
    printf("%d\n",ans);
    output();
    return 0;
}
262144

相关文章: