Advertisement
Guest User

PermutationSort

a guest
Jan 2nd, 2018
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.30 KB | None | 0 0
  1. /*
  2.  * Copyright (c) 2018 Simon Klein, Google Inc.
  3.  * All rights reserved.
  4.  */
  5.  
  6. import java.util.*;
  7.  
  8. /**
  9.  * Solves the problem proposed at http://codeforces.com/blog/entry/56731.
  10.  */
  11. public class PermutationSort {
  12.   static final Map<DpKey, Integer> dp = new HashMap<>();
  13.   // Temporary map to remap numbers to ones in [0,n) for some n <= 1000.
  14.   static final int[] smap = new int[1001];
  15.  
  16.   // Finds the cheapest cost of sorting original[0, len).
  17.   // If reduce = false, then the numbers in original[0, len) all are in the
  18.   // range [0, len) and needn't be normalized.
  19.   static int solve(final int[] original, final int len, final boolean reduce) {
  20.     if(len<=1) return 0;
  21.     DpKey originalKey = new DpKey(original, len);
  22.     if(dp.containsKey(originalKey)) return dp.get(originalKey);
  23.  
  24.     // Remap numbers to range [0, len).
  25.     int[] v = Arrays.copyOf(original, len);
  26.     if (reduce) {
  27.       Arrays.sort(v);
  28.       for (int i = 0; i < len; i++) smap[v[i]] = i;
  29.       for (int i = 0; i < len; i++) v[i] = smap[original[i]];
  30.     }
  31.  
  32.     DpKey normalizedKey = reduce ? new DpKey(v, len) : originalKey;
  33.     if(reduce && dp.containsKey(normalizedKey)) return dp.get(normalizedKey);
  34.  
  35.     // Find max element.
  36.     int x = -1, xi = -1;
  37.     for(int i = 0; i<len; i++) {
  38.       if(v[i]>x) { x = v[i]; xi = i; }
  39.     }
  40.  
  41.     // Max element is already in position.
  42.     if(xi+1==len){
  43.       int cost = solve(v, len-1, false);
  44.       dp.put(originalKey, cost);
  45.       if(reduce) dp.put(normalizedKey, cost);
  46.       return cost;
  47.     }
  48.  
  49.     // Calculate cost of using case 1.
  50.     for(int i = xi; i<len-1; i++) v[i] = v[i+1];
  51.     v[len-1] = x;
  52.     final int case1 = solve(v, len-1, false) + (xi+1) + len;
  53.     for(int i = len-1; i>xi; i--) v[i] = v[i-1];
  54.     v[xi] = x;
  55.  
  56.     // Calculate cost of using case 2.
  57.     int case2 = solve(v, xi, true);
  58.     // Create and init segment tree with elements in v[0, xi), i.e. HL.
  59.     int pow2 = 1;
  60.     while(pow2<len) pow2 *= 2;
  61.     final int[] tree = new int[2*pow2];
  62.     for(int i = 0; i<xi; i++) tree[pow2+v[i]] = 1;
  63.     for(int i = pow2-1; i>0; i--) tree[i] = tree[2*i] + tree[2*i+1];
  64.     // For each element in HR...
  65.     for(int i = xi+1; i<len; i++) {
  66.       // Find the number of elements in HL less than v[i].
  67.       final int tmp = v[i];
  68.       int headset = 0;
  69.       for(int j = 1, l = 0, r = pow2; l<=r && l<tmp;) {
  70.         int mid = (r+l)/2;
  71.         if(mid<=tmp){ headset += tree[2*j]; l = mid; j=2*j+1; }
  72.         else { j = 2*j; r = mid;}
  73.       }
  74.       // Move v[i] into HL.
  75.       case2 += (i+1) + (headset + 1);
  76.       if(case2>=case1) break;
  77.       for(int j = pow2+tmp; j>0; j/=2) tree[j]++;
  78.     }
  79.  
  80.     // Pick the cheaper option of the two.
  81.     int cost = Math.min(case1, case2);
  82.     dp.put(originalKey, cost);
  83.     if(reduce) dp.put(normalizedKey, cost);
  84.     return cost;
  85.   }
  86.  
  87.   public static void main(String[] args) {
  88.     // Yeah the input has some weird format, convert it to the normal one.
  89.     Scanner in = new Scanner(System.in);
  90.     int len = Integer.parseInt(in.nextLine());
  91.     int[] v = Arrays.stream(in.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
  92.     int[] tmp = Arrays.copyOf(v,len);
  93.     Arrays.sort(tmp);
  94.     Map<Integer, Integer> map = new HashMap<>();
  95.     for(int i = 0; i<len; i++) map.put(tmp[i], len-i-1);
  96.     for(int i = 0; i<len; i++) v[i] = map.get(v[i]);
  97.  
  98.     // int[] v = {4,5,1,3,2};
  99.     long time = System.currentTimeMillis();
  100.     System.out.println("Svar: " + solve(v, v.length, false));
  101.     time = System.currentTimeMillis() - time;
  102.     System.out.println("Time: " + time/1000d);
  103.   }
  104.  
  105.   private static class DpKey {
  106.     final int[] v;
  107.     final int len;
  108.     final int hashcode;
  109.     DpKey(int[] vv, int llen) {
  110.       // Max value is 1000, so we fit 3 numbers in an int.
  111.       len = (llen+2)/3;
  112.       v = new int[len];
  113.       for(int i = 0; i<llen; i++) {
  114.         int j = i/3;
  115.         v[j] = (v[j]<<10)+vv[i];
  116.       }
  117.       int h = 1;
  118.       for(int i = 0; i<len; i++) h = h*31 + v[i];
  119.       hashcode = h;
  120.     }
  121.  
  122.     public int hashCode() {
  123.       return hashcode;
  124.     }
  125.  
  126.     public boolean equals(Object o) {
  127.       DpKey other = (DpKey)o;
  128.       if(len!=other.len || hashcode!=other.hashcode) return false;
  129.       for(int i = 0; i<len; i++) if(v[i]!=other.v[i]) return false;
  130.       return true;
  131.     }
  132.   }
  133. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement