【主席树】Gym - 101237A - MEX-Query

主席树里每个值的位置存当前该值出现的最右位置。

如果root[r]的前缀主席树中,某值最右位置大于等于l,说明该值出现在了l,r中。

所以主席树维护区间最小值,如果左半值域的最小值<l,则说明左半值域有值未在l,r出现,则查询左子树;否则查询右子树。

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 1000010
struct Node{int v,lc,rc;}T[N*22];
int root[N],e;
void Insert(int pre,int cur,int p,int v,int l,int r)
{
    if(l==r)
      {
        T[cur].v=v;
        return;
      }
    int m=(l+r>>1);
    if(p<=m)
      {
        T[cur].lc=++e;
        T[cur].rc=T[pre].rc;
        Insert(T[pre].lc,T[cur].lc,p,v,l,m);
      }
    else
      {
        T[cur].rc=++e;
        T[cur].lc=T[pre].lc;
        Insert(T[pre].rc,T[cur].rc,p,v,m+1,r);
      }
    T[cur].v=min(T[T[cur].lc].v,T[T[cur].rc].v);
}
int Goal;
int Query(int R,int l,int r)
{
    if(l==r) return l;
    int m=(l+r>>1);
    if(T[T[R].lc].v<Goal) return Query(T[R].lc,l,m);
    else return Query(T[R].rc,m+1,r);
}
int n,m,a[N];
int main()
{
    int x,y;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
      {
      	scanf("%d",&x);
        root[i]=++e;
        Insert(root[i-1],root[i],x+1,i,1,1000001);
      }
    scanf("%d",&m);
    for(;m;--m)
      {
        scanf("%d%d",&x,&y);
        Goal=x;
        printf("%d\n",Query(root[y],1,1000001)-1);
      }
    return 0;
}
时间: 2024-10-15 00:16:18

【主席树】Gym - 101237A - MEX-Query的相关文章

[主席树]HDOJ3874 Necklace

题意:n个数 m个询问 询问的是[l, r]区间内不同的数的和 没有修改,静态的主席树即可 与 SPOJ QUERY 一样 将重复的元素建树即可 注意范围:$N \le  50000$ 每个值不超过1000000 也就是加起来会爆int 要用LL 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 #define lson l, m 5 #define rson m+1, r 6 const i

牛课练习赛34 Flittle w and Discretization 主席树维护Mex

ittle w and Discretization 主席树维护Mex. 每个右端点 r 维护出一棵 在[1, r ] 区间中 其他所有的 值离这个 r 最近的的位置是多少. 然后询问区间[L,R]的时候,从rt[R] 出发,然后如果左儿子的中所有出线位置的最小值 >= L, 则说明他们所有的点都出线在这个区间内了,然后往右走. 否则就说明左边有点没有出线过,需要往左走. 代码: #include<bits/stdc++.h> using namespace std; #define F

【bzoj1803】Spoj1487 Query on a tree III DFS序+主席树

题目描述 You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. 输入 The first line contains one integer n (1 <= n <

【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. Input

BZOJ_1803_Spoj1487 Query on a tree III_主席树+dfs序

BZOJ_1803_Spoj1487 Query on a tree III_主席树 Description You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. I

bzoj 1803: Spoj1487 Query on a tree III(主席树)

题意 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小到大排序第k个点) 假设没有两个相同的点权. 输入格式: 第一行为整数n,第二行为点权,接下来n-1行为树边,接下来一行为整数m,下面m行为两个整数x,k,代表query(x,k) 输出格式: m行,输出每次查询的结果. 题解 先一遍dfs,然后建个主席树,带上去直接跑一跑就好了 我忘了注意dfs序的位置和原来的编号……结果调了半天啥都调不出来…… 1 //minamot

[CF893F]Subtree Minimum Query (主席树)

题面: 传送门:http://codeforces.com/problemset/problem/893/F 题目大意:给你一颗有根树,点有权值,问你每个节点的子树中距离其不超过k的点的权值的最小值.(边权均为1,强制在线) Solution 这题很有意思. 我们一般看到这种距离不超过k的题目,第一反应一般是建以深度为下标,以dfs序为时间轴的的主席树. 很不幸,区间最小值并不能通过减去历史状态得出某个子树的状态. 所以说,这题妙在思想的转换. 考虑以dfs序为下标,以深度为时间轴建一颗主席树.

PT07J - Query on a tree III DFS序 + 主席树

dfs序编号后跑权值主席树 但写起来是真的麻烦,总是wa,只能拿出模板过了 #include<bits/stdc++.h> const int N = 100001; using namespace std; struct node { int to, ne; } e[N<<1]; int n, m, len, l1, l2; int id[N], rk[N], eid[N], re[N]; int he[N], a[N], b[N]; int val[N << 5],

【复习笔记】主席树

昨天在写带修改主席树的时候,咸鱼zcysky发现自己似乎根本不会写主席树 于是正好找个空复习下-- 主席树的原理不用我扯了,主席树为啥能求k大,大概在它可以用历史版本存下区间的前缀和,求的时候差分下就能提出我要求的区间. 不过这么搞的话不要忘了离散化. 1.kth number 就是上面的裸题,不要手贱写bits就好. 1 #include<iostream> 2 #include<cstdio> 3 #define N 100010 4 #include<algorithm