B - 로렌스
나는 하드를 찾으 주제는, 하드 DP는이 방정식에 쓸 수 없습니다.
문제에 온라인 솔루션을 읽고,이 전환 방정식 DP를 이해하는 데 시간이 오래 읽기
DP가 [I] [j]가 1 ~ 가리 J의 J 비트 및 I 개의 섹션으로 최소 중량 끝내고
그런 배열 W [A, B], (A)의 중량을 B로하고,이 정의는 접두사되는 것이 아니라, 피사체의 종류 및 중량
이러한 4 5 1 2 개 전략적 가치가 4 * 5 + 1 + 4 * 4 * 2 * 5 + 1 + 5 * 2 * 2 + 1 = 49이다 ㄴ이다.
[A는 B] 49 = w
그 후, 발을 정의 [I] == 1 난] 수단 승 그 접두사 중량과 발 [I] = 브로 [I-1] + 합 [I-1] * A [i]를
이 w는 [A, B] 직접적으로 도입 될 수 있지만, 접두사에 의해 가압 될 수 있기 때문이다.
求 w [A + 1, B] = 브로 [B] -val [A] - (합 [B] -sum [A]) * 합계 [A]
그런 다음 방정식은 DP 그것을 실행할 수 있습니다
DP는 [내가 J]를 분 (DP [I-1, K] + w [K + 1, J를) =
그러나 직접적인 폭력 N ^ 3은 최적화되어야하고,이 수식은 같은 최적화 식의 기울기 전에 통해 가압되지 않고 위에 확실히 아니다.
만약 DP 일반적 경사 DP 최적화함으로써 최적화 될 수있는 가치가 있는데, [I-1, K] K 첨가.
그리고이 공식 전에 도입 될 수있다 (참조하기 전에 - 진주 HDU - 1300 양자 기울기 DP + D 경사 DP - 3507 - 인쇄 기사이 기사는 HDU했다 )
令 F [H]는 DP가 = [I-1] [H] -val [H] + 합 [H] * 합계 [H]
所以 G [H, K = (F [H] - F [K) / (합계 [H] -sum [K]) <합 [J]
그런 다음 같은 추론한다
I가 있는지> J> K G [I, J]> G [J, K]
1 G [I, J]> Gj에, K]> [t] 합보다 우수한 케이 J는 J 바람직한 비 I
(2) G [I, J]> 합 [t]는> G는 [J는 K] j는 이하 난 후, 바람직하게는, J K의 비율보다 바람직
3 합 [t]> G [I, J]> G [J, K] 우수 우수 비 K j에 j를보다 나는
만약 I> J> K G [I, J] <G [J, K]
1 G [내가 J] <G [J, K] <합 [t]는 k 개의 I의 J 비가 우수 우수 J보다 작
2. G [I, J] <합 [t] <G [J, K] I 우수 우수 비 K j에 j를보다
우수 우수 3 합 [t] <G [I, J] <G [J, K] J 비의 I J K의
이러한 상황에서, J가 확실히 배제 될 그래서 후방으로부터 삽입되면 그 때에 앞 J,이 경사의 기울기 번호와 이전 구성의 수보다 적은 구성하면
음,이 확실히 J 아니다.
이 합이 단순하고 접두어이므로 큐 모노톤 DP를 최적화 할 수있다.
#INCLUDE <cstdio> #INCLUDE <CString을> #INCLUDE <cstdlib> #INCLUDE <알고리즘> #INCLUDE <큐> #INCLUDE <벡터> #INCLUDE <iostream> #INCLUDE < 문자열 > #DEFINE INF 0x3f3f3f3f #DEFINE inf64 0x3f3f3f3f3f3f3f3f 사용 공간 표준; CONST의 INT maxn 1E5 + = 10 ; 타입 정의 긴 긴 LL; LL의 DP [ 1100 ] [ 1100 ], 합계 [ 1100 ], 발 [ 1,100]이 [ 1100 ]; INT의 케 [maxn]; 최대 LL ( int로 I, INT의 J, INT의 K) { 리턴 - DP [I 1 [J] - 브로 [J] + 합 [J]를 * 합계 [J] - (DP [I - 1 [K] - 발 [K] + 합 [K] * 합계 [K]); } (아래하겠다 INT의 J, INT의 K) { 리턴 합 [J]를 - 합 [K]을; } LL DP ( int로 I, INT의 J, INT의 K) { 복귀 DP [I - 1 [K] + 브로 [J] - 브로 [K] - (합 [J] - 합 [K]) * 합계 [K ]; } INT 의 main () { INT의 N, m; 반면 (는 scanf ( " %의 D % d에 " , N, m) && (N + m)) { 합 [ 0 ] = 0 ; 발 [ 0 ] = 0 ; 위한 ( int로 I = 1 ; 나는 <= N; I ++는 ) { 는 scanf ( " %의 LLD를 " , & A [I]); 합 [I] = 합계 [I - 1 ] + A [I]; 발 [I] = 브로 [I - 1 ] + 합 [I - 1* A [I]; } 대 ( INT I = 1. ; I <= N-; I는 ++) DP [ 1이다. ] [I] = 브로 [I]; // 참고이 주제 초기화 용 ( INT I = 2 ; I <= m + . 1 ; I ++ ) { INT의 머리 = 0 , 꼬리 = 0 ; // 주의 DP는 [내가 j는 상기 정의의 단부 I 블록의 최소값으로 J 인 케 [꼬리 ++] = I - 1이다. ] / / 다음 세그먼트 나 블록으로 분할 될 수 있기 때문에, 앞의 숫자는 적어도 I-1이 고려되어야하고, 참고 경우 누락되지 전체적으로 밖이어서 될 수 위해 ( INT의 J = I, J <= N-, J ++ ) { // 이 볼 수 있어야 J 주부터 시작 상태 (머리 + 1 <꼬리가 && (I, 케 [헤드 + 1 ] 케 [헤드]) <= 합 [J] * 다운 (케 [헤드 + 1 ] 케 [헤드])) 헤드 ++ ; DP는 [I] [J] = DP (I, J, 케 [헤드]); 상태 (머리 + 1 - <꼬리 (I, J, 케 [꼬리 && 1 ) * 다운 (케 [꼬리 -] 1 ] 케 [꼬리 - 2 ]) <= 최대 (I, 케 [꼬리 - 1 ] 케을 [꼬리 - 2 ]) * 다운 (j, 케 [꼬리 - 1 ])) tail-- ; 케 [꼬리 ++] = J; } } 의 printf ( " % LLD \ 없음 " , DP [m + 1 ] [N]); } 반환 0 ; }