题意:
    按照顺序接收重量为 4, 3, 2, 1, 4的block时,可按照重量为4 –> 3 –>2 –> 1 的顺序推成塔,然后最后为了装饰塔顶,可以使用重量为4的block。
    用例:
    1
    5
    2 4
    1 2
    3 3
    2 6
    1 4
    —> # 13

    1. package indexTree;
    2. import java.io.BufferedReader;
    3. import java.io.FileInputStream;
    4. import java.io.InputStreamReader;
    5. import java.util.Arrays;
    6. import java.util.Comparator;
    7. import java.util.StringTokenizer;
    8. public class 积木游戏3{
    9. static int T,N;
    10. static long[] indexTree;
    11. static block[] blockArr;
    12. static class block{
    13. int index;
    14. int w;
    15. int val;
    16. int max;
    17. public block(int index, int w, int val, int max) {
    18. this.index = index;
    19. this.w = w;
    20. this.val = val;
    21. this.max = max;
    22. }
    23. }
    24. static class compM implements Comparator<block>{
    25. @Override
    26. public int compare(block o1, block o2) {
    27. if (o1.w != o2.w) {
    28. return o2.w-o1.w;
    29. }else {
    30. //此处的排序 当重量相同时 index 按照 降序排列
    31. // 因为题目中要求相同重量的不能叠放。
    32. return o2.index-o1.index;
    33. }
    34. }
    35. }
    36. public static void main(String[] args) throws Exception {
    37. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    38. StringTokenizer st = new StringTokenizer(br.readLine());
    39. T = Integer.parseInt(st.nextToken());
    40. for (int i0 = 1; i0 <= T; i0++) {
    41. st = new StringTokenizer(br.readLine());
    42. N = Integer.parseInt(st.nextToken());
    43. blockArr = new block[N];
    44. for (int i = 0; i < N; i++) {
    45. st = new StringTokenizer(br.readLine());
    46. int weightTemp = Integer.parseInt(st.nextToken());
    47. int valTemp = Integer.parseInt(st.nextToken());
    48. blockArr[i] = new block(i,weightTemp, valTemp,0);
    49. }
    50. //获取当前点之后的最大值
    51. for (int i = N-2; i >=0; i--) {
    52. blockArr[i].max = Math.max(blockArr[i+1].max, blockArr[i+1].val);
    53. }
    54. Arrays.sort(blockArr,0,N,new compM());
    55. int lastNodeNum = 1;
    56. while(lastNodeNum < N) {
    57. lastNodeNum <<=1;
    58. }
    59. indexTree = new long[2*lastNodeNum];
    60. long ans = 0;
    61. for (int i = 0; i < N; i++) {
    62. long sum = query(lastNodeNum, lastNodeNum+blockArr[i].index)+blockArr[i].val;
    63. update(lastNodeNum+blockArr[i].index, sum);
    64. ans = Long.max(ans, sum+blockArr[i].max);
    65. }
    66. System.out.println("#"+i0+" "+ans);
    67. }
    68. }
    69. private static void update(int index, long val) {
    70. while (index > 0) {
    71. indexTree[index] = Math.max(val,indexTree[index]);
    72. index >>= 1;
    73. }
    74. }
    75. private static long query(int s, int e) {
    76. long max = 0;
    77. while (s <= e) {
    78. if (s % 2 == 1) max = Long.max(max, indexTree[s]);
    79. if (e % 2 == 0) max = Long.max(max, indexTree[e]);
    80. s = (s + 1) >> 1;
    81. e = (e - 1) >> 1;
    82. }
    83. return max;
    84. }
    85. }