給一個長度爲 \(n\) 的序列 \(a\) 。c++
對於第 \(i\) 秒,咱們能夠選擇若干個位置上的數加上 \(2^{i-1}\) 。spa
問最少在第幾秒的時候,能夠使得 \(a_1 \leq a_2\leq...\leq a_n\) 。code
首先不難注意到,對於前 \(i\) 秒,咱們能夠使得一個數加上 \(x\in[1,2^i-1]\)。ip
也就是說對於前 \(i\) 秒,咱們能夠讓一個數 \(x\) 變成 \([x,x+2^i-1]\) 內的任意一個數。get
考慮一下這個式子 \(a_1 \leq a_2\leq...\leq a_n\) ,顯然,\(a_i\) 越小,則 \(a_{i+1}\) 至 \(a_n\) 越有 " 操做空間 " 。string
又由於操做只會致使數變大,因此咱們顯然是不要去動這個 \(a_1\) 。it
接着考慮一下 \(a_2\) :io
以此類推,咱們接着考慮 \(a_3,a_4,...,a_n\) ,假設咱們如今考慮到第 \(i\) 位:class
這樣考慮完這 \(n\) 位便可求出答案,\(\mathcal{O(n \log \log size)}\),其中 \(size\) 表示的是值域大小。gc
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; namespace IO { static char buf[1 << 20], *fs, *ft; inline char gc() { if (fs == ft) { ft = (fs = buf) + fread(buf, 1, 1 << 20, stdin); if (fs == ft) return EOF; } return *fs ++; } #define gc() getchar() inline int read() { int x = 0, f = 1; char s = gc(); while (s < '0' || s > '9') {if (s == '-') f = -f; s = gc();} while (s >= '0' && s <= '9') {x = x * 10 + s - '0'; s = gc();} return x * f; } } using IO :: read; const int N = 200100; int n; long long a[N]; void work() { n = read(); for (int i = 1; i <= n; i ++) a[i] = read(); int ans = 0; for (int i = 2; i <= n; i ++) { if (a[i - 1] <= a[i]) continue; int l = 1, r = 33; while (l < r) { int mid = (l + r) / 2; long long delta = (1ll << mid) - 1; if (a[i - 1] <= a[i] + delta) r = mid; else l = mid + 1; } ans = max(ans, l); a[i] = a[i - 1]; } printf("%d\n", ans); } int main() { int T = read(); while (T --) work(); return 0; }