似乎是个大水题,多数的题解是暴力分块区间的做法。
这里介绍一种略微优秀一点的做法,截至发表时在UOJ上用时rk1,询问次数挺少说不定也有rk1
首先用O(n+1)的代价找到最大最小
考虑答案下限显然有max((r - l)/(n-1) , 1)
我们考虑动态分块,每次划分的块是当前的ans,显然在这个区间里面的数都没有什么卵用
不断更新当前的区间L , R , 同时找出当前区间的mn和mx的时候更新答案
维护上一次的找的的最大/最小
在跑的时候顺便动态更新块的大小,因为显然如果一个块啥都没有答案肯定可以更新变大
注意细节问题
我相信你们都没听懂还是看代码吧
1 #include"gap.h" 2 #include<bits/stdc++.h> 3 using namespace std; 4 long long num[100005]; 5 long long brout(int T,int n) 6 { 7 int w = n; 8 long long l = 0 , r = 1e18; 9 int L = 1 , R = n; 10 num[0] = num[n + 1] = 1e18; 11 long long mn , mx; 12 long long ans = 0; 13 while(w && (r - l) > ans && L <= R){ 14 MinMax(l , r , &mn , &mx); 15 if(mn == mx){num[L] = mn;ans = max(ans , max(num[R + 1] - mn , mn - num[L - 1]));break;} 16 num[L] = mn , num[R] = mx; 17 l = mn + 1; 18 r = mx - 1; 19 if(L > 1){ ans = max(ans , max(num[L] - num[L - 1] , num[R + 1] - num[R]));} 20 if(L == R - 1) ans = max(ans , num[R] - num[L]); 21 L++ , R--; 22 } 23 return ans; 24 } 25 long long findGap(int T,int n) 26 { 27 if(T == 1) return brout(T , n); 28 long long l = 0 , r = 1e18; 29 num[0] = num[n + 1] = 1e18; 30 long long mn , mx , mn2 , mx2; 31 long long ans = 1 , LL , RL; 32 MinMax(0 , 1e18 , &l , &r); 33 if(n == 2) return r - l; 34 LL = l , RL = r; 35 ans = max((r - l) / (n - 1), 1LL); 36 while((r - l) > ans){ 37 bool f = 0; 38 mx = -1; 39 do{ 40 if(mx != -1) {LL = mx;} 41 if(f) l = l + ans; 42 if(r - l <= ans) break; 43 f = 1; 44 ans = max(ans , l - LL); 45 MinMax(l + 1 , min(l + ans , r - 1), &mn , &mx); 46 }while((mx == -1 || (mn - LL <= ans)) && (r - l > ans)); 47 l = l + ans; 48 if(mn != -1) {ans = max(ans , mn - LL);LL = mx;} 49 if(r - l <= ans) break; 50 mn = -1;f = 0; 51 do{ 52 if(mn != -1) {RL = mn;} 53 if(f) r = r - ans; 54 if(r - l <= ans) break; 55 f = 1; 56 ans = max(ans , RL - r); 57 MinMax(max(r - ans , l + 1) , r - 1 , &mn , &mx); 58 }while((mn == -1 || (RL - mx <= ans)) && (r - l > ans)); 59 r = r - ans; 60 if(mx != -1) {ans = max(ans , RL - mx);RL = mn;} 61 if(r - l <= ans) break; 62 } 63 l = LL , r = RL; 64 if(l < r - 1){ 65 MinMax(l + 1 , r - 1 , &mn , &mx); 66 if(mn != -1) ans = max(ans , max(mn - LL , RL - mx)); 67 else ans = max(ans , RL - LL); 68 } 69 else ans = max(ans , RL - LL); 70 return ans; 71 }