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 }

转载于:https://www.cnblogs.com/Itst/p/10092580.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值