Submission #332950

#TimeUsernameProblemLanguageResultExecution timeMemory
332950KWang31Split the sequence (APIO14_sequence)Java
71 / 100
645 ms131072 KiB
//Convex Hull Trick, verified on CF319C (319 is ID) import java.io.*; import java.util.*; public class sequence{ static class FastReader { BufferedReader br; StringTokenizer st; public FastReader() { br = new BufferedReader(new InputStreamReader(System.in)); } String next() { while (st == null || !st.hasMoreElements()) { try { st = new StringTokenizer(br.readLine()); } catch (IOException e) { e.printStackTrace(); } } return st.nextToken(); } int nextInt() { return Integer.parseInt(next()); } } static int[] M; static long[] B; static int[] ind; static int pointer=0; static short[][] ch; static boolean[][] b1; static boolean[][] b2; static int N; static int sz; public static void main(String[] args){ FastReader br=new FastReader(); N=br.nextInt(); int K=br.nextInt(); int[] s=new int[N]; long[] dp=new long[N]; long[] dp2=new long[N]; ch=new short[N][K]; b1=new boolean[N][K];b2=new boolean[N][K]; s[0]=br.nextInt(); for(int i=1;i<N;i++){s[i]=s[i-1]+br.nextInt(); } //System.out.println(Arrays.toString(s)); for (int i = 0; i < K; i++) { M=new int[N]; B=new long[N]; ind=new int[N]; sz=0; add(s[0],-(long)s[0]*s[0],i); for (int j = 1; j < N; j++) { dp2[j]=query((long)s[j],N*i+j); add(s[j], dp[j]-(long)s[j]*s[j],Math.max(j,i)); //System.out.println(M); //System.out.println(B); } for (int j = 0; j < N; j++) { dp[j]=dp2[j]; } //System.out.println(Arrays.toString(dp)); } //System.out.println(Arrays.toString(dp)); System.out.println(dp[N-1]); StringBuilder sb=new StringBuilder(); int[] arl=new int[K]; int cur=N-1; for (int i = K-1; i >=0; i--) { if(b1[cur][i] && b2[cur][i])cur=(int) 4*ch[cur][i]+3; else if(b1[cur][i]) cur=(int) 4*ch[cur][i]+1; else if(b2[cur][i]) cur=(int) 4*ch[cur][i]+2; else cur=(int) 4*ch[cur][i]; arl[i]=cur+1; } //StringBuilder is actually quite memory consuming for (int i = 0; i <K; i++) { sb.append(arl[i]+" "); } System.out.println(sb.toString()); } public static boolean bad(int l1, int l2, int l3){//Using doubles to prevent overflow return (M[l1]-M[l3])*((double)B[l2]-B[l1])>=(M[l1]-M[l2])*((double)B[l3]-B[l1]); //Intersection of l1 and l3 must be ABOVE l2 //For l2 to be added //l1.m>l2.m>l3.m, as sum is strictly increasing } public static void add(int m, long b, int i){ M[sz]=m; B[sz]=b; ind[sz]=i; sz++; while(sz>=3 && bad(sz-3,sz-2,sz-1)){ M[sz-2]=m; B[sz-2]=b; ind[sz-2]=i; sz--; } } public static long query(long x, int j){ if(pointer>=sz){pointer=sz-1;} while(pointer<sz-1 && M[pointer+1]*x+B[pointer+1] > M[pointer]*x+B[pointer]){ pointer++; } ch[j%N][j/N]=(short)(ind[pointer]/4); if(ind[pointer]%2==1){ b1[j%N][j/N]=true; } if(ind[pointer]%4>=2){ b2[j%N][j/N]=true; } return M[pointer]*x+B[pointer]; } } //Debugging: //Are you sure your algorithm is correct? //Bounds: long //Special cases: n=0,1? //Make sure you remove your debugging code before you submit!
#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...