• 主席树 找区间内不同的数


    越来越觉得主席树这个东西需要意会了……太TM深奥了TAT (๑•̀ㅂ•́)و✧

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #define REP(i, s, n) for(int i = s; i <= n; i ++)
     7 #define RAP(i, n, s) for(int i = n; i >= s; i --)
     8 using namespace std;
     9 const int maxn = 100000 + 10;
    10 const int maxnode = 20 * maxn;
    11 int ls[maxnode], rs[maxnode], root[maxn], s[maxnode];
    12 int A[maxn], num[maxn], last[maxn], from[maxn], n, Q, ms;
    13 int find(int v){
    14     int L = 1, R = n, M;
    15     while(L <= R){
    16         M = L + R >> 1;
    17         if(num[M] < v) L = M + 1;
    18         else R = M - 1;
    19     }
    20     return L;
    21 }
    22 void build(int x, int& y, int L, int R, int v){
    23     s[y = ++ ms] = s[x] + 1;
    24     if(L == R) return ;
    25     rs[y] = rs[x]; ls[y] = ls[x];
    26     int M = L + R >> 1;
    27     if(v <= M) build(ls[x], ls[y], L, M, v);
    28     else build(rs[x], rs[y], M + 1, R, v);
    29     return ;
    30 }
    31 int query(int x, int& y, int L, int R, int v){
    32     if(L == R) return s[y] - s[x]; //把数量扔回来Σ( ° △ °|||) ︴Σ( ° △ °|||) ︴Σ( ° △ °|||)︴ 
    33     int M = L + R >> 1;
    34     if(v <= M) return query(ls[x], ls[y], L, M, v);
    35     else return (s[ls[y]] - s[ls[x]]) + query(rs[x], rs[y], M + 1, R, v); //左边的别忘加了,注意是孩子的o(* ̄3 ̄)o 
    36 }
    37 void read(int &x){
    38     x = 0; int sig = 1; char ch = getchar();
    39     while(!isdigit(ch)) { if(ch == '-') sig = -1; ch = getchar(); }
    40     while(isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
    41     x *= sig; return ;
    42 }
    43 void init(){
    44     read(n); read(Q);
    45     REP(i, 1, n) read(A[i]), num[i] = A[i];
    46     sort(num + 1, num + 1 + n);
    47     REP(i, 1, n){
    48         build(root[i - 1], root[i], 0, n, last[from[i] = find(A[i])]);//每次更新一下头,去建“尾”的主席树 
    49         last[from[i]] = i;//别忘了更新现在到哪里了
    50     }
    51     return ;
    52 }
    53 void work(){
    54     int L, R;
    55     while(Q --){
    56         read(L); read(R);
    57         printf("%d
    ", query(root[L - 1], root[R], 0, n, L - 1)); //你想想啊我们要找在这个范围内最后出现在L-1里东西的数量吧? 
    58     }
    59     return ;
    60 }
    61 void print(){
    62 
    63     return ;
    64 }
    65 int main(){
    66     init();
    67     work();
    68     print();
    69     return 0;
    70 }
  • 相关阅读:
    java实现第五届蓝桥杯出栈次序
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    java实现第五届蓝桥杯年龄巧合
    Java使用RandomAccessFile读写文件
    Java 实现文件随机读写-RandomAccessFile
    NIO 中文乱码自我解决的简单DEMO
    NIO 中文乱码问题的解决代码实现
  • 原文地址:https://www.cnblogs.com/chxer/p/4423342.html
Copyright © 2020-2023  润新知