제출 #216245

#제출 시각아이디문제언어결과실행 시간메모리
216245Giantpizzahead수열 (APIO14_sequence)Java
100 / 100
1502 ms119540 KiB
/* * The order of the splits does not matter (figure this out by trying smaller cases). * Use some algebra to transform the cost into a more workable form. * ab + ac + bc = [(a + b + c)^2 - (a^2 + b^2 + c^2)] / 2 * (a + b + c) remains constant, so the goal is to find the best way to split the array into pieces a, b, c such that * the sum of the squares is minimized. This can be done using dynamic programming, with a form of convex hull optimization. * Runtime: O(NK) */ import java.util.*; import java.io.*; public class sequence { final long INF = 5876543212345678L; int N, K; int[] arr; int[][] from; ConvexHull hull; sequence(BufferedReader in, PrintWriter out) throws IOException { StringTokenizer st = new StringTokenizer(in.readLine()); N = Integer.parseInt(st.nextToken()); K = Integer.parseInt(st.nextToken()) + 1; arr = new int[N]; st = new StringTokenizer(in.readLine()); for (int i = 0; i < N; i++) arr[i] = Integer.parseInt(st.nextToken()); hull = new ConvexHull(); from = new int[K + 1][N + 1]; long[][] dp = new long[2][N + 1]; Arrays.fill(dp[0], INF); dp[0][0] = 0; int currDP = 1; for (int i = 1; i <= K; i++) { hull.bot = 0; hull.top = 0; int currX = 0; for (int j = 0; j <= N; j++) { // Transition from best state State s = hull.query(currX); if (s == null) dp[currDP][j] = INF; else { dp[currDP][j] = s.eval(currX); from[i][j] = s.i; } // Add new transition if (dp[1-currDP][j] != INF) hull.add(currX, dp[1-currDP][j], j); // Move currX if (j != N) currX += arr[j]; } // System.out.println(Arrays.toString(dp[currDP])); // System.out.println(Arrays.toString(from[i])); currDP = 1 - currDP; } long answer = 0; for (int i = 0; i < N; i++) answer += arr[i]; answer *= answer; answer -= dp[1-currDP][N]; answer /= 2; out.println(answer); int loc = N; for (int i = K; i > 1; i--) { loc = from[i][loc]; if (i != K) out.print(' '); out.print(loc); } out.println(); } class ConvexHull { State[] states; int bot, top; ConvexHull() { states = new State[N]; for (int i = 0; i < N; i++) states[i] = new State(-1, -1, -1); bot = 0; top = 0; } void add(int sx, long sy, int i) { // Remove states with the same sx while (top - bot >= 2 && states[top-1].sx == sx) { if (states[top-1].sy > sy) top--; else return; // This state is useless } // Remove useless states while (top - bot >= 2) { State prev = states[top-1]; State prev2 = states[top-2]; if (prev2.intersect(prev) >= prev.intersect(sx, sy)) { // prev is useless top--; } else break; } // Add this state states[top].sx = sx; states[top].sy = sy; states[top++].i = i; } /** * Assumes x is in increasing order. */ State query(int x) { // Remove outdated states while (top - bot >= 2) { if (states[bot].eval(x) >= states[bot+1].eval(x)) { // Bottom state is outdated bot++; } else break; } if (top - bot == 0) return null; return states[bot]; } } class State { int sx, i; long sy; State(int sx, long sy, int i) { this.sx = sx; this.sy = sy; this.i = i; } double intersect(State o) { return intersect(o.sx, o.sy); } double intersect(int osx, long osy) { double part1 = (sy - osy) / (2 * (sx - osx)); double part2 = (sx + osx) / 2; return part1 + part2; } long eval(int x) { return sy + (long) (sx - x) * (sx - x); } } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out)); new sequence(in, out); in.close(); out.close(); } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...