qwerty787788

FBR3DWA

Sep 12th, 2020
1,485
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.24 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.List;
  5. import java.util.StringTokenizer;
  6.  
  7. public class D {
  8.     FastScanner in;
  9.     PrintWriter out;
  10.  
  11.     static final boolean USE_DOWNLOADS_FOLDER = true;
  12.  
  13.     List<Integer> buildChain(int[] a, int root) {
  14.         List<Integer> res = new ArrayList<>();
  15.         while (true) {
  16.             boolean ok = false;
  17.             for (int i = 0; i < a.length; i++) {
  18.                 if (a[i] == root) {
  19.                     res.add(i);
  20.                     root = i;
  21.                     ok = true;
  22.                     break;
  23.                 }
  24.             }
  25.             if (!ok) {
  26.                 break;
  27.             }
  28.         }
  29.         return res;
  30.     }
  31.  
  32.     class Chain {
  33.         int len;
  34.         boolean connectsToFirst;
  35.         boolean connectsToSecond;
  36.  
  37.         public Chain(int len, boolean connectsToFirst, boolean connectsToSecond) {
  38.             this.len = len;
  39.             this.connectsToFirst = connectsToFirst;
  40.             this.connectsToSecond = connectsToSecond;
  41.         }
  42.     }
  43.  
  44.     void solve() {
  45.         int tc = in.nextInt();
  46.         for (int t = 0; t < tc; t++) {
  47.             System.err.println("test: " + t + "/" + tc);
  48.             int n = in.nextInt();
  49.             int[] a = new int[n];
  50.             int[] b = new int[n];
  51.             for (int i = 0; i < n; i++) {
  52.                 a[i] = in.nextInt() - 1;
  53.                 b[i] = in.nextInt() - 1;
  54.             }
  55.             int q0ans = 0;
  56.             for (int i = 0; i < n; i++) {
  57.                 if (a[i] == b[i]) {
  58.                     q0ans++;
  59.                 }
  60.             }
  61.             List<Integer> first = buildChain(a, n);
  62.             List<Integer> second = buildChain(a, n + 1);
  63.             List<Integer> firstExpected = buildChain(b, n);
  64.             List<Integer> secondExpected = buildChain(b, n + 1);
  65.             long[] res = new long[n + 2];
  66.             for (int q = 0; q <= 2 && q <= n; q++) {
  67.                 for (int c = 0; c <= n; c++) {
  68.                     int[][] prec = null;
  69.                     if (q == 1 && first.size() <= c && second.size() <= c && n <= 2 * c) {
  70.                         int stay = Math.max(0, n - c);
  71.                         int alrScore = 0;
  72.                         boolean[] canShuffle = new boolean[n];
  73.                         Arrays.fill(canShuffle, true);
  74.                         for (int i = 0; i < stay; i++) {
  75.                             int myId = first.get(i);
  76.                             canShuffle[myId] = false;
  77.                             int realNextId = i == 0 ? n : (first.get(i - 1));
  78.                             if (b[myId] == realNextId) {
  79.                                 alrScore++;
  80.                             }
  81.                         }
  82.                         for (int i = 0; i < stay; i++) {
  83.                             int myId = second.get(i);
  84.                             canShuffle[myId] = false;
  85.                             int realNextId = i == 0 ? (n + 1) : (second.get(i - 1));
  86.                             if (b[myId] == realNextId) {
  87.                                 alrScore++;
  88.                             }
  89.                         }
  90.                         boolean[] hasPrevCanShuffle = new boolean[n];
  91.                         for (int i = 0; i < n; i++) {
  92.                             if (canShuffle[i] && b[i] < n) {
  93.                                 hasPrevCanShuffle[i] = true;
  94.                             }
  95.                         }
  96.                         List<Chain> allChains = new ArrayList<>();
  97.                         int firstLast = stay == 0 ? n : first.get(stay - 1);
  98.                         int secondLast = stay == 0 ? (n + 1) : second.get(stay - 1);
  99.                         for (int i = 0; i < n; i++) {
  100.                             if (!canShuffle[i]) {
  101.                                 continue;
  102.                             }
  103.                             if (hasPrevCanShuffle[i]) {
  104.                                 continue;
  105.                             }
  106.                             int cur = i;
  107.                             int len = 0;
  108.                             while (cur < n && canShuffle[cur]) {
  109.                                 cur = b[cur];
  110.                                 len++;
  111.                             }
  112.                             boolean endFirst = cur == firstLast;
  113.                             boolean endSecond = cur == secondLast;
  114.                             allChains.add(new Chain(len, endFirst, endSecond));
  115.                         }
  116.                         int[] dp = new int[c + 1];
  117.                         int[] ndp = new int[c + 1];
  118.                         Arrays.fill(dp, Integer.MIN_VALUE / 2);
  119.                         dp[0] = alrScore;
  120.                         for (Chain chain : allChains) {
  121.                             Arrays.fill(ndp, Integer.MIN_VALUE / 2);
  122.                             for (int curLenF = 0; curLenF < dp.length; curLenF++) {
  123.                                 int cur = dp[curLenF];
  124.                                 if (cur < 0) {
  125.                                     continue;
  126.                                 }
  127.                                 for (int useLen = 0; useLen <= chain.len; useLen++) {
  128.                                     int addScore = Math.max(useLen - 1, 0);
  129.                                     int useLenRigth = chain.len - useLen;
  130.                                     addScore += Math.max(useLenRigth - 1, 0);
  131.                                     if (useLen > 0 && chain.connectsToFirst) {
  132.                                         addScore++;
  133.                                     }
  134.                                     if (useLenRigth > 0 && chain.connectsToSecond) {
  135.                                         addScore++;
  136.                                     }
  137.                                     int nLen = curLenF + useLen;
  138.                                     if (nLen < ndp.length) {
  139.                                         ndp[nLen] = Math.max(ndp[nLen], cur + addScore);
  140.                                     }
  141.                                 }
  142.                             }
  143.                             int[] tmp = dp;
  144.                             dp = ndp;
  145.                             ndp = tmp;
  146.                         }
  147.                         prec = new int[c + 1][c + 1];
  148.                         for (int i = 0; i < prec.length; i++) {
  149.                             Arrays.fill(prec[i], -1);
  150.                         }
  151.                         for (int lenFirst = 0; lenFirst < dp.length; lenFirst++) {
  152.                             int realLenFirst = lenFirst + stay;
  153.                             int realLenSecond = n - realLenFirst;
  154.                             if (realLenSecond > c || realLenFirst > c) {
  155.                                 continue;
  156.                             }
  157.                             prec[realLenFirst][realLenSecond] = Math.max(prec[realLenFirst][realLenSecond], dp[lenFirst]);
  158.                             if (prec[realLenFirst][realLenSecond] > n) {
  159.                                 throw new AssertionError();
  160.                             }
  161.                         }
  162.                         for (int i = 0; i < prec.length; i++) {
  163.                             for (int j = 0; j < prec[i].length; j++) {
  164.                                 int cur = prec[i][j];
  165.                                 if (i + 1 < prec.length) {
  166.                                     prec[i + 1][j] = Math.max(prec[i + 1][j], cur);
  167.                                 }
  168.                                 if (j + 1 < prec[i].length) {
  169.                                     prec[i][j + 1] = Math.max(prec[i][j + 1], cur);
  170.                                 }
  171.                             }
  172.                         }
  173.                     }
  174.                     for (int x = 0; x <= c; x++) {
  175.                         for (int y = 0; y <= c; y++) {
  176.                             long multiplier = q < 2 ? 1 : (n - 2 + 1);
  177.                             multiplier *= x < c ? 1 : (n - c + 1);
  178.                             multiplier *= y < c ? 1 : (n - c + 1);
  179.                             int v = -1;
  180.                             boolean badInitState = first.size() > c || second.size() > c || n > 2 * c || n > x + y;
  181.                             if (!badInitState) {
  182.                                 if (q == 0) {
  183.                                     if (first.size() <= x && second.size() <= y) {
  184.                                         v = q0ans;
  185.                                     }
  186.                                 } else if (q == 1) {
  187.                                     v = prec[x][y];
  188.                                 } else {
  189.                                     if (firstExpected.size() <= x && secondExpected.size() <= y) {
  190.                                         v = n;
  191.                                     } else {
  192.                                         v = n - 1;
  193.                                     }
  194.                                 }
  195.                             }
  196.                             if (v > n) {
  197.                                 throw new AssertionError();
  198.                             }
  199.                             res[v + 1] += multiplier;
  200.                         }
  201.                     }
  202.                 }
  203.             }
  204.             out.print("Case #" + (t + 1) + ":");
  205.             for (long r : res) {
  206.                 out.print(" " + r);
  207.             }
  208.             out.println();
  209.         }
  210.     }
  211.  
  212.  
  213.     void run() {
  214.         try {
  215.             if (USE_DOWNLOADS_FOLDER) {
  216.                 File inFile = getLatestFilefromDir("/Users/bminaiev/Downloads");
  217.                 System.err.println("WILL USE FILE: " + inFile.toString());
  218.                 in = new FastScanner(inFile);
  219.             } else {
  220.                 in = new FastScanner(new File("A.in"));
  221.             }
  222.             out = new PrintWriter(new File("D.out"));
  223.  
  224.             solve();
  225.  
  226.             out.close();
  227.         } catch (FileNotFoundException e) {
  228.             e.printStackTrace();
  229.         }
  230.     }
  231.  
  232.     private File getLatestFilefromDir(String dirPath) {
  233.         File dir = new File(dirPath);
  234.         File[] files = dir.listFiles();
  235.         if (files == null || files.length == 0) {
  236.             return null;
  237.         }
  238.  
  239.         File lastModifiedFile = files[0];
  240.         for (int i = 1; i < files.length; i++) {
  241.             if (lastModifiedFile.lastModified() < files[i].lastModified()) {
  242.                 lastModifiedFile = files[i];
  243.             }
  244.         }
  245.         return lastModifiedFile;
  246.     }
  247.  
  248.     void runIO() {
  249.  
  250.         in = new FastScanner(System.in);
  251.         out = new PrintWriter(System.out);
  252.  
  253.         solve();
  254.  
  255.         out.close();
  256.     }
  257.  
  258.     class FastScanner {
  259.         BufferedReader br;
  260.         StringTokenizer st;
  261.  
  262.         public FastScanner(File f) {
  263.             try {
  264.                 br = new BufferedReader(new FileReader(f));
  265.             } catch (FileNotFoundException e) {
  266.                 e.printStackTrace();
  267.             }
  268.         }
  269.  
  270.         public FastScanner(InputStream f) {
  271.             br = new BufferedReader(new InputStreamReader(f));
  272.         }
  273.  
  274.         String next() {
  275.             while (st == null || !st.hasMoreTokens()) {
  276.                 String s = null;
  277.                 try {
  278.                     s = br.readLine();
  279.                 } catch (IOException e) {
  280.                     e.printStackTrace();
  281.                 }
  282.                 if (s == null)
  283.                     return null;
  284.                 st = new StringTokenizer(s);
  285.             }
  286.             return st.nextToken();
  287.         }
  288.  
  289.         boolean hasMoreTokens() {
  290.             while (st == null || !st.hasMoreTokens()) {
  291.                 String s = null;
  292.                 try {
  293.                     s = br.readLine();
  294.                 } catch (IOException e) {
  295.                     e.printStackTrace();
  296.                 }
  297.                 if (s == null)
  298.                     return false;
  299.                 st = new StringTokenizer(s);
  300.             }
  301.             return true;
  302.         }
  303.  
  304.         int nextInt() {
  305.             return Integer.parseInt(next());
  306.         }
  307.  
  308.         long nextLong() {
  309.             return Long.parseLong(next());
  310.         }
  311.  
  312.         double nextDouble() {
  313.             return Double.parseDouble(next());
  314.         }
  315.     }
  316.  
  317.     public static void main(String[] args) {
  318.         new D().run();
  319.     }
  320. }
Advertisement
Add Comment
Please, Sign In to add comment