输入输出样例

样例1

输入

  1. 3
  2. 3 9 4 1 3 4
  3. 0 0 2 0 4 4

输出

  1. 7 13 2

题解一:模拟

模拟。维护两个队列分别存储候选果子(每次摘从中选择)和受限的果子(暂时不能摘),每次摘完更新果子的状态和两个队列。

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.util.*;
  5. public class Main {
  6. public static void main(String[] args) throws IOException {
  7. BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
  8. final int n = 2 * Integer.parseInt(reader.readLine());
  9. int[] a = new int[n];
  10. int[] b = new int[n];
  11. String[] strs = reader.readLine().split(" ");
  12. for (int i = 0; i < n; ++i) {
  13. a[i] = Integer.parseInt(strs[i]);
  14. }
  15. strs = reader.readLine().split(" ");
  16. for (int i = 0; i < n; ++i) {
  17. b[i] = Integer.parseInt(strs[i]);
  18. }
  19. long start = System.currentTimeMillis();
  20. Fruit[] fruits = new Fruit[n + 1];
  21. for (int i = 1; i <= n; ++i) {
  22. fruits[i] = new Fruit(i, a[i - 1], b[i - 1]);
  23. }
  24. for (int i = 1; i <= n; ++i) {
  25. if (b[i - 1] > 0) {
  26. ++fruits[b[i - 1]].cnt;
  27. }
  28. }
  29. // 候选果子
  30. List<Fruit> doList = new ArrayList<Fruit>(n);
  31. // 受限的果子
  32. List<Fruit> undoList = new ArrayList<Fruit>(n);
  33. for (int i = 1; i <= n; ++i) {
  34. fruits[i].update();
  35. if (fruits[i].isWork) {
  36. doList.add(fruits[i]);
  37. } else {
  38. undoList.add(fruits[i]);
  39. }
  40. }
  41. List<Integer> ans = new ArrayList<Integer>(n);
  42. while (!doList.isEmpty()) {
  43. Pair max = null;
  44. for (int i = 0; i < doList.size(); ++i) {
  45. // 选苹果
  46. if (doList.get(i).id > n / 2) {
  47. continue;
  48. }
  49. for (int j = 0; j < doList.size(); ++j) {
  50. // 选梨
  51. if ((i == j) || (doList.get(j).id <= n / 2)) {
  52. continue;
  53. }
  54. Pair pair = new Pair(doList.get(i), doList.get(j));
  55. if (pair.compareTo(pair, max) > 0) {
  56. max = pair;
  57. }
  58. }
  59. }
  60. ans.add(max.val);
  61. for (Iterator<Fruit> it = doList.iterator(); it.hasNext();) {
  62. Fruit tmp = it.next();
  63. if ((tmp.id == max.apple.id) || (tmp.id == max.pear.id)) {
  64. if (tmp.next > 0) {
  65. --fruits[tmp.next].cnt;
  66. }
  67. it.remove();
  68. }
  69. }
  70. for (Iterator<Fruit> it = undoList.iterator(); it.hasNext();) {
  71. Fruit tmp = it.next();
  72. tmp.update();
  73. if (tmp.isWork) {
  74. doList.add(tmp);
  75. it.remove();
  76. }
  77. }
  78. }
  79. for (int i = 0; i < ans.size() - 1; ++i) {
  80. System.out.print(ans.get(i) + " ");
  81. }
  82. System.out.println(ans.get(ans.size() - 1));
  83. System.out.println(System.currentTimeMillis() - start + "ms");
  84. }
  85. }
  86. class Pair {
  87. Fruit apple;
  88. Fruit pear;
  89. int val;
  90. public Pair(Fruit o1, Fruit o2) {
  91. apple = o1;
  92. pear = o2;
  93. val = o1.val ^ o2.val;
  94. }
  95. public int compareTo(Pair o1, Pair o2) {
  96. if (o1 == null) {
  97. return -1;
  98. }
  99. if (o2 == null) {
  100. return 1;
  101. }
  102. if (o1.val > o2.val) {
  103. return 1;
  104. } else if (o1.val < o2.val) {
  105. return -1;
  106. }
  107. if (o1.apple.val > o2.apple.val) {
  108. return 1;
  109. } else if (o1.apple.val < o2.apple.val) {
  110. return -1;
  111. }
  112. if (o1.apple.id > o2.apple.id) {
  113. return 1;
  114. } else if (o1.apple.id < o2.apple.id) {
  115. return -1;
  116. }
  117. if (o1.pear.id > o2.pear.id) {
  118. return 1;
  119. } else if (o1.pear.id < o2.pear.id) {
  120. return -1;
  121. }
  122. return 0;
  123. }
  124. }
  125. class Fruit {
  126. // 水果编号
  127. int id;
  128. // 美味度
  129. int val;
  130. // 关联的水果编号
  131. // 0表示无效
  132. int next;
  133. // 被关联的水果数量
  134. int cnt;
  135. // 是否可以摘取
  136. boolean isWork;
  137. public void update() {
  138. if (cnt == 0) {
  139. isWork = true;
  140. }
  141. }
  142. public Fruit(int id, int val, int next) {
  143. super();
  144. this.id = id;
  145. this.val = val;
  146. this.next = next;
  147. this.cnt = 0;
  148. this.isWork = false;
  149. }
  150. }