UVA1451 Average
阿新 • • 發佈:2018-12-23
www line name log 自然 bool lib tor 這就是
嘟嘟嘟
看到比值,就想到01分數規劃,令\(ans = \frac{\sum a_i}{\sum l_i}\),其中\(l\)表示長度,所以\(l_i\)都是\(1\)。
然後變一下型,得到\(\sum (a_i - ans) = 0\)。這就是01分數規劃的標準形式了。
所以我們按套路二分,每一次數組中的元素就是\(a_i - mid\),然後求最大連續和。
如果大於等於\(0\),說明\(mid\)小了,向右額分;否則向左二分。
求最大連續和的時候,因為要記錄左右端點,所以用前綴和的方法求最方便。
預處理前綴和。枚舉右端點,那麽左端點自然要取最小的,這樣才能使差最大,\(O(n)\)掃一遍的時候一起維護。
總復雜度\(O(n \log n)\)
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(‘ ‘) #define Mem(a, x) memset(a, x, sizeof(a)) #define In inline typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 1e5 + 5; inline ll read() { ll ans = 0; char ch = getchar(), last = ‘ ‘; while(!isdigit(ch)) {last = ch; ch = getchar();} while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - ‘0‘; ch = getchar();} if(last == ‘-‘) ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar(‘-‘); if(x >= 10) write(x / 10); putchar(x % 10 + ‘0‘); } int n, len; char s[maxn]; int id1, id2; db sum[maxn]; bool judge(db x) { for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + s[i] - ‘0‘ - x; int pos = 0; db Max = -INF; for(int i = len; i <= n; ++i) { if(sum[i - len] <= sum[pos] - eps) pos = i - len; if(sum[i] - sum[pos] > Max + eps) id1 = pos + 1, id2 = i, Max = sum[i] - sum[pos]; } return Max > -eps; } void solve() { db L = 0, R = 1; while(R - L > eps) { db mid = (L + R) / 2; if(judge(mid)) L = mid; else R = mid; } judge(L + eps); write(id1), space, write(id2), enter; } int main() { int T = read(); while(T--) { n = read(); len = read(); scanf("%s", s + 1); solve(); } return 0; }
UVA1451 Average