トピック:http://codeforces.com/contest/889/problem/E
本当に楽しいこの質問。
公式の説明は良い質問でした。
I [i]は近隣で維持するが、にくくすることができるとの間のセグメントを考えます。
これは、k個の元の形式として表現+ iがXを*。xが限りDPにおける記録アレイとして、「X <= ...この式Xを満たすために」は、それぞれIを渡すために、行に固有の値であり、そのような範囲の数は、一番下に予約されています。
その後、動作しないコードを書きます。
書式#include <cstdioを> する#include <CStringの> の#include <アルゴリズム> 書式#include <マップ> に#define LL長い長い 使って 名前空間はstdを、 LLのRDN() { LL RET = 0。ブール FX = 1。チャー CH = GETCHAR()。 一方、(CH> ' 9 ' || CH < ' 0 '){ 場合(CH == ' - ')FX = 0 ; CH = GETCHAR();} 一方(CH> = ' 0' && CH <= ' 9 ')RET = RET * 10 + CH- ' 0 '、CH = GETCHAR()。 返す FXをRET: - ?RET; } LL Mxが(-1,11,11- b)は{ 返す > bは?A:B;} のconst int型 N = 2E5 + 5、M = N * 20 。 int型N、TOT、L [N]、R [N]、[N]、DP [M]、DYの【のM] LL、ANS。 地図 <LL、INT > MP [N]。 INT メイン() { N = (RDN)。 以下のために(int型 I = 1 [I] = iが++; iが<= N)RDN(); R [ 1 ] = ++ TOT。DP [TOT] = 0 ; DY [TOT] [= 1 ] - 1 。 以下のために(int型 i = 1 ; iがN <I ++は) { L [I + 1 ] = R [i]は= TOTを、 用(INT J = L [I] + 1、D、J <= R [i]は、J ++ ) { LL kは = DP [J]、R = DY [J]、TP = R%A [I + 1 ]。 もし(R> [I + = 1 ]) { もし!(MP [I + 1 ] .count([I + 1 - ] 1)) { MP [I + 1 ] [[I + 1 ] - 1 ] = ++ TOT。 dyが[TOT]は = [I + 1 ] - 1 。 } 、D = MP [I + 1 ] [[I + 1 ] - 1 ]。 DP [D] =はMx(DP [D]、K + i *が(R-TP [I + 1 ]))。 } もし(!融点[I + 1 ] .count(TP)) { MP [I + 1 ] [TP] = ++ TOT。DY [TOT = TP。 } 、D = MP [I + 1] [TP]。 DP [D] =はMx(DP [D]、K + iが(R- * TP))を、 } } のための(int型 I = 1 [N] + 1 ; I <= TOT iは++ ) { LLのK = DP [i]は、R = DYの[I]。 ANS =はMx(ANS、N * R + K)。 } のprintf(" %LLDする\ n " 、ANS)。 リターン 0 ; }
位置を通過することができ、Rは、変わっていません。それは彼らがより多くのような位置iにおける使用のようにスペース、およびとの位置のI + 1を取ることはなかったです。
そして、問題解決の多くをコピーします。それが通過できるように、元のマップ。
書式#include <cstdioを> する#include <CStringの> の#include <アルゴリズム> 書式#include <マップ> に#define LL長い長い 使って 名前空間はstdを、 LLのRDN() { LL RET = 0。ブール FX = 1。チャー CH = GETCHAR()。 一方、(CH> ' 9 ' || CH < ' 0 '){ 場合(CH == ' - ')FX = 0 ; CH = GETCHAR();} 一方(CH> = ' 0' && CH <= ' 9 ')RET = RET * 10 + CH- ' 0 '、CH = GETCHAR()。 返す FXをRET: - ?RET; } LL Mxが(-1,11,11- b)は{ 返す > bは?A:B;} のconst int型 N = 2E5 + 5 。 INT 、N; [N] LL、ANS。 マップ <-1,11,11-> 融点; マップ <-1,11,11-> ::イテレータit。 INT メイン() { N(= RDN)。以下のために(int型 I = 1 [I] = iが++; iが<= N) )(RDN と、 融点[[1 ] - 1 ] = 0 。 以下のために(int型私= 1 ; iがN <; Iは++ ) { ながら(1 ) { が mp.end()=。it-- ; LLのR =(※)1次回、K =(* IT).second。 もし(R <[I + 1 ])ブレーク。 mp.erase(それ)。 融点[[I + 1 ] - 1 ] =はMx(MP [[I + 1 ] - 1 ]、K + I *(RRの%[I + 1 ] -a [I + 1 ]))。 融点[R%[I + 1 ] =はMx(MP [R%は[I + 1 ]、K + iは(RR%の[I + * 1 ]))。 } } のためには、(それがmp.beginを()=;!それ= mp.end();それ++ ) ANS =はMx(ANS、N *(* IT)1次回+(* IT).second)。 printf(" %LLDする\ n " 、ANS)。 リターン 0 ; }