1. 程式人生 > >Luogu4137 Rmq problem/mex 主席樹

Luogu4137 Rmq problem/mex 主席樹

傳送門


用主席樹水莫隊題……

我們對於字首和建立主席樹,對於主席樹中的每一個葉子節點表示它對應的數字最後出現的位置的編號,非葉子節點求左右節點的最小值,那麼對於每一次詢問$l,r$就是在第$r$棵主席樹上找到權值$<l$的最左端的點,在主席樹上二分即可。

 1 #include<bits/stdc++.h>
 2 #define mid ((l + r) >> 1)
 3 #define min(x,y) x < y ? x : y
 4 #define pushup(x) Tree[x].minN = min(Tree[Tree[x].l].minN , Tree[Tree[x].r].minN)
 5
//This code is written by Itst 6 using namespace std; 7 8 inline int read(){ 9 int a = 0; 10 bool f = 0; 11 char c = getchar(); 12 while(c != EOF && !isdigit(c)){ 13 if(c == '-') 14 f = 1; 15 c = getchar(); 16 } 17 while(c != EOF && isdigit(c)){
18 a = (a << 3) + (a << 1) + (c ^ '0'); 19 c = getchar(); 20 } 21 return f ? -a : a; 22 } 23 24 const int MAXN = 200010; 25 struct query{ 26 int l , r , ind; 27 }que[MAXN]; 28 struct node{ 29 int l , r , minN; 30 }Tree[MAXN * 40]; 31 int ans[MAXN] , root[MAXN] , N , M , cntNode;
32 33 void insert(int& x , int p , int l , int r , int tar , int num){ 34 x = ++cntNode; 35 Tree[x] = Tree[p]; 36 if(l == r) 37 Tree[x].minN = num; 38 else{ 39 if(mid >= tar) 40 insert(Tree[x].l , Tree[p].l , l , mid , tar , num); 41 else 42 insert(Tree[x].r , Tree[p].r , mid + 1 , r , tar , num); 43 pushup(x); 44 } 45 } 46 47 int query(int x , int l , int r , int minN){ 48 if(l == r) 49 return l; 50 if(Tree[Tree[x].l].minN < minN) 51 return query(Tree[x].l , l , mid , minN); 52 return query(Tree[x].r , mid + 1 , r , minN); 53 } 54 55 int main(){ 56 #ifndef ONLINE_JUDGE 57 freopen("4137.in" , "r" , stdin); 58 //freopen("4137.out" , "w" , stdout); 59 #endif 60 N = read(); 61 M = read(); 62 for(int i = 1 ; i <= N ; ++i){ 63 int a = read(); 64 if(a < N) 65 insert(root[i] , root[i - 1] , 0 , N , a , i); 66 else 67 root[i] = root[i - 1]; 68 } 69 for(int i = 1 ; i <= M ; ++i){ 70 int a = read() , b = read(); 71 printf("%d\n" , query(root[b] , 0 , N , a)); 72 } 73 return 0; 74 }