$O(nC)$
s[i]: m[1...i]의 합
파라매트릭 서치를 하기 위해 문제를 평균이 p이하가 될 수 있는지 결정하는 문제로 바꿔보자.
즉,
(s[n]-s[i]+s[j])/(n-i+j)<=p (1<=j<i<n) 인 i, j가 존재하는지 확인하면 된다.
위 식은
s[n]-p*n+(p*i-s[i])-(p*j-s[j])<=0 과 동치이고
이는 f(x)=p*x-s[x]을 최댓값으로 만드는 x=j를 기억하면 매 i마다 s[n]-p*n+f(i)-f(j)의 최솟값을 O(1)에 찾을 수 있어서
매번 O(n)에 평균을 p이하로 만들 수 있는지 확인이 가능하다.
#include<cstdio> const int MXN = 1e5; int n, s[MXN + 1]; bool f(double a) { double maxi = a - s[1]; for (int i = 2; i < n; i++) { if (s[n] - a*n + a*i - s[i] - maxi <= 0) return 1; if (a*i - s[i]>maxi) maxi = a*i - s[i]; } return 0; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", s + i), s[i] += s[i - 1]; double low = 1, up = 1e4, mid; while (up - low > 1e-6) { mid = (low + up) / 2; f(mid) ? up = mid : low = mid; } printf("%.3lf", mid); return 0; }
댓글 없음 :
댓글 쓰기