比较弱,只写了金组和银组,铂金组的第一题。
【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; }