• 题解【CF1338A Powered Addition】


    [ exttt{Description} ]

    给一个长度为 (n) 的序列 (a)

    对于第 (i) 秒,我们可以选择若干个位置上的数加上 (2^{i-1})

    问最少在第几秒的时候,可以使得 (a_1 leq a_2leq...leq a_n)

    [ exttt{Solution} ]

    • 首先不难注意到,对于前 (i) 秒,我们可以使得一个数加上 (xin[1,2^i-1])

    • 也就是说对于前 (i) 秒,我们可以让一个数 (x) 变成 ([x,x+2^i-1]) 内的任意一个数。

    • 考虑一下这个式子 (a_1 leq a_2leq...leq a_n) ,显然,(a_i) 越小,则 (a_{i+1})(a_n) 越有 " 操作空间 " 。

    • 又因为操作只会导致数变大,所以我们显然是不要去动这个 (a_1)

    • 接着考虑一下 (a_2)

      • (a_1 leq a_2) ,则已经满足题目要求,为了给后面的数留 " 操作空间 " 所以不要动它。
      • (a_1 > a_2) ,则二分最小 (x) 的满足 (a_1 leq a_2 + 2^x-1) ,用 (x) 更新答案,再令 (a_2 = a_1)
    • 以此类推,我们接着考虑 (a_3,a_4,...,a_n) ,假设我们现在考虑到第 (i) 位:

      • (a_{i-1} leq a_i) ,则已经满足题目要求,为了给后面的数留 " 操作空间 " 所以不要动它。
      • (a_{i-1} > a_i) ,则二分最小 (x) 的满足 (a_{i-1} leq a_i + 2^x-1) ,用 (x) 更新答案,再令 (a_i = a_{i-1})
    • 这样考虑完这 (n) 位即可求出答案,(mathcal{O(n log log size)}),其中 (size) 表示的是值域大小。

    [ exttt{Code} ]

    #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
    ", ans);
    }
    
    int main() {
    
    	int T = read();
    
    	while (T --)    work();
    
    	return 0;
    }
    

    [ exttt{Thanks} exttt{for} exttt{watching} ]

  • 相关阅读:
    201703-1 分蛋糕
    201812-2 小明放学
    201812-1 小明上学
    逆向_Easy_vb
    逆向_入门逆向
    代码审计_弱类型整数大小比较绕过
    代码审计_数组返回NULL绕过
    代码审计_md5()函数
    代码审计_urldecode二次编码绕过
    代码审计_extract变量覆盖
  • 原文地址:https://www.cnblogs.com/cjtcalc/p/12688959.html
Copyright © 2020-2023  润新知