• little w and Discretization --- 题解 (线段树好题)


    目录

    little w and Discretization --- 题解 (线段树好题)

    题目大意:

    思路解析:

    代码实现:


     

    little w and Discretization --- 题解 (线段树好题)

    题目大意:

            

    思路解析:

             离散化数组满足以下要求:

                 (1) 保留原数组的大小关系, 即当a[i] > [j], 有b[i]>b[j],当a[i]=a[j]有b[i]=b[j],当a[i]

                   (2)b数组有正整数构成

                    (3)在满足以上两点情况下,b数组的每个元素都要求尽可能小

            这道题要求那么将 al -- ar这个区间的元素进行离散化,离散化后将有多少个元素与原来不同。这个答案对于每个相同的数组是相同的,例如 1 2 3 5 6 7一定会离散化为1 2 3 4 5 6,可以发现只要当数组中有元素大于数组未出现的最小整数 ,那么这些元素离散化后一定与原来的元素不同。则问题转化为这个查询区间中最小未出现的元素为那个,并且大于它的元素有多少个。因为我们知道区间长度,那么答案可以转化为 len - cnt, cnt表示小于等于它的元素有多少个。

    cnt可以用数组数组查询区间和来解决,那么难点变为了,如何求区间中未出现的最小整数。

     cnt还有个小细节,需要注意,假如我们查询画框数组,那么未出现的最小整数,小于等于它的个数为1,但是我们查询某个区间小于等于的数是较复杂的,我们可以转化为 求 1-2这个区间小于等于2的个数和1-7这个区间小于等于2的个数,这里需要用到离线操作

            

    求区间中未出现的最小整数

     

    我们发现,我们如果将查询区间后的数组元素更新在线段树上后,线段树的查询就会变得复杂,所以这里也需要用到离线操作。

    代码实现:

            

    1. import java.io.*;
    2. import java.util.*;
    3. public class Main {
    4. static long mod = (int) 1e9 + 7;
    5. static int base = 131;
    6. static int MAXN = 300005;
    7. static int[] cnt = new int[MAXN];
    8. static int[] a = new int[MAXN];
    9. static int[] leaf = new int[MAXN];
    10. static int n;
    11. public static void main(String[] args) throws IOException {
    12. FastScanner f = new FastScanner();
    13. PrintWriter w = new PrintWriter(System.out);
    14. n = f.nextInt();
    15. for (int i = 1; i <= n; i++) {
    16. a[i] = f.nextInt();
    17. if (a[i] > n) a[i] = n + 1;
    18. }
    19. SegTree seg = new SegTree();
    20. seg.build(1, 1, n);
    21. int m = f.nextInt();
    22. PriorityQueue<Pair> pairs = new PriorityQueue<Pair>(new Comparator<Pair>() {
    23. @Override
    24. public int compare(Pair o1, Pair o2) {
    25. return o1.r - o2.r;
    26. }
    27. });
    28. int[] ans = new int[m];
    29. for (int i = 0; i < m; i++) {
    30. int x = f.nextInt();
    31. int y = f.nextInt();
    32. ans[i] = (y - x + 1);
    33. pairs.add(new Pair(x, y, i));
    34. }
    35. PriorityQueue<Res> res = new PriorityQueue<>(new Comparator<Res>() {
    36. @Override
    37. public int compare(Res o1, Res o2) {
    38. return o1.pos - o2.pos;
    39. }
    40. });
    41. for (int i = 1; i <= n; i++) {
    42. seg.change_leaf(i, a[i]);
    43. while(!pairs.isEmpty() && pairs.peek().r == i){
    44. Pair cur = pairs.poll();
    45. int tt = seg.mex(cur.l);
    46. res.add(new Res(-1, tt, cur.id, cur.r));
    47. if (cur.l != 1){
    48. res.add(new Res(1, tt, cur.id, cur.l - 1));
    49. }
    50. }
    51. }
    52. for (int i = 1; i <= n; i++) {
    53. update(a[i]);
    54. while(!res.isEmpty() && res.peek().pos == i){
    55. Res cur = res.poll();
    56. ans[cur.id] += cur.type * sum(cur.num);
    57. }
    58. }
    59. for (int i = 0; i < m; i++) {
    60. w.println(ans[i]);
    61. }
    62. w.flush();
    63. w.close();
    64. }
    65. public static void update(int x){
    66. for (int i = x; i <= n; i += i & - i) {
    67. cnt[i] += 1;
    68. }
    69. }
    70. public static int sum(int x){
    71. int res = 0;
    72. while (x > 0){
    73. res += cnt[x];
    74. x -= x & -x;
    75. }
    76. return res;
    77. }
    78. public static class Res{
    79. int type, num, id, pos;
    80. public Res(int type, int num, int id, int pos) {
    81. this.type = type;
    82. this.num = num;
    83. this.id = id;
    84. this.pos = pos;
    85. }
    86. }
    87. public static class Pair{
    88. int l, r, id;
    89. public Pair(int l, int r, int id) {
    90. this.l = l;
    91. this.r = r;
    92. this.id = id;
    93. }
    94. }
    95. public static class Node{
    96. int l;
    97. int r;
    98. int pos;
    99. }
    100. public static class SegTree{
    101. Node[] t = new Node[4 * MAXN];
    102. public SegTree() {
    103. for (int i = 0; i < 4 * MAXN; i++) {
    104. t[i] = new Node();
    105. }
    106. }
    107. public void build(int root, int l, int r){
    108. t[root].l = l;
    109. t[root].r = r;
    110. if (l != r){
    111. build(root << 1, l, (l + r) >> 1);
    112. build(root << 1 | 1, (l + r) >> 1 | 1, r);
    113. }else {
    114. t[root].pos = 0;
    115. leaf[l] = root;
    116. }
    117. }
    118. public void change_leaf (int id, int num){
    119. t[leaf[num]].pos = id;
    120. int root = leaf[num] >> 1;
    121. while (root > 0){
    122. t[root].pos = Math.min(t[root << 1].pos, t[root << 1 | 1].pos);
    123. root >>= 1;
    124. }
    125. }
    126. public int mex(int l){
    127. int root = 1;
    128. while (t[root].l != t[root].r){
    129. if (t[root << 1].pos >= l){
    130. root = root << 1 | 1;
    131. }else {
    132. root = root << 1;
    133. }
    134. }
    135. return t[root].l - 1;
    136. }
    137. }
    138. private static class FastScanner {
    139. final private int BUFFER_SIZE = 1 << 16;
    140. private DataInputStream din;
    141. private byte[] buffer;
    142. private int bufferPointer, bytesRead;
    143. private FastScanner() throws IOException {
    144. din = new DataInputStream(System.in);
    145. buffer = new byte[BUFFER_SIZE];
    146. bufferPointer = bytesRead = 0;
    147. }
    148. private short nextShort() throws IOException {
    149. short ret = 0;
    150. byte c = read();
    151. while (c <= ' ') c = read();
    152. boolean neg = (c == '-');
    153. if (neg) c = read();
    154. do ret = (short) (ret * 10 + c - '0');
    155. while ((c = read()) >= '0' && c <= '9');
    156. if (neg) return (short) -ret;
    157. return ret;
    158. }
    159. private int nextInt() throws IOException {
    160. int ret = 0;
    161. byte c = read();
    162. while (c <= ' ') c = read();
    163. boolean neg = (c == '-');
    164. if (neg) c = read();
    165. do ret = ret * 10 + c - '0';
    166. while ((c = read()) >= '0' && c <= '9');
    167. if (neg) return -ret;
    168. return ret;
    169. }
    170. public long nextLong() throws IOException {
    171. long ret = 0;
    172. byte c = read();
    173. while (c <= ' ') c = read();
    174. boolean neg = (c == '-');
    175. if (neg) c = read();
    176. do ret = ret * 10 + c - '0';
    177. while ((c = read()) >= '0' && c <= '9');
    178. if (neg) return -ret;
    179. return ret;
    180. }
    181. private char nextChar() throws IOException {
    182. byte c = read();
    183. while (c <= ' ') c = read();
    184. return (char) c;
    185. }
    186. private String nextString() throws IOException {
    187. StringBuilder ret = new StringBuilder();
    188. byte c = read();
    189. while (c <= ' ') c = read();
    190. do {
    191. ret.append((char) c);
    192. } while ((c = read()) > ' ');
    193. return ret.toString();
    194. }
    195. private void fillBuffer() throws IOException {
    196. bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
    197. if (bytesRead == -1) buffer[0] = -1;
    198. }
    199. private byte read() throws IOException {
    200. if (bufferPointer == bytesRead) fillBuffer();
    201. return buffer[bufferPointer++];
    202. }
    203. }
    204. }

     

  • 相关阅读:
    记一次 .NET某企业数字化平台 崩溃分析
    C#流Stream与IO详解(5)——读取文件的详细流程
    关于企业如何替换 FTP 和加速 FTP 的问题
    ARMday04(开发版简介、LED点灯)
    vue的基本使用
    2022年中南大学夏令营面试经验
    MySQL数据库用户管理
    Android内存优化/内存泄漏排查
    adb删除系统应用
    极智开发 | CUDA线程模型与全局索引计算方式
  • 原文地址:https://blog.csdn.net/weixin_73936404/article/details/136375987