https://www.luogu.org/problemnew/show/P3147
此题与上一题完全一样,唯一不一样的就是数据范围;
上一题是248,而这一题是262144;
普通的区间dp表示状态表示法根本存不下,
这时我们就要想另外的状态表示法;
#include <bits/stdc++.h> #define read read() #define up(i,l,r) for(int i = (l);i <=(r); i++) using namespace std; int read { int x = 0; char ch = getchar(); while(ch < 48 || ch > 57) ch = getchar(); while(ch >= 48 && ch <= 57) {x = 10 * x + ch - 48; ch = getchar();} return x; } int n,f[270000][60],ans;// 262144 -> 2 ^ 18 //所以最多 40 + 18 = 58; //f[i][j]表示到第i个数,得到数值为j,向右合并的最右端点.(左闭右开 -> [,) ) int main() { freopen("262144.in","r",stdin); n = read; up(i,1,n) f[i][(read)] = i + 1; up(j,2,58) up(i,1,n) { if(f[i][j] == 0) f[i][j] = f[f[i][j-1]][j-1]; if(f[i][j]) ans = j;//right : 包括上面的,f[i][j] > 0时才更新 //else ans = j; //-> false //容易写错 //f[i][j]大于0是关键; } printf("%d",ans); return 0; }