标签:
越来越觉得主席树这个东西需要意会了……太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\n", 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 }
标签:
原文地址:http://www.cnblogs.com/chxer/p/4423342.html