zoukankan      html  css  js  c++  java
  • luogu P4137 Rmq Problem / mex

    区间求 mex 问题。

    对序列建一棵以权值为下标的主席树。每个节点记录:当前区域内每个权值的前一个出现位置的最小值。查询 ([l,r]) 内的 mex 时拿出 (r) 这棵线段树,在上面操作:如果左边区间有最小值小于 (l),那么递归到左区间,否则递归进入右区间。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    const int N=200009;
    int n,m,a[N],pool,rt[N];
    struct Tree
    {
    	int l,r,Last;
    	#define l(x) b[x].l
    	#define r(x) b[x].r
    	#define Last(x) b[x].Last
    }b[N*32];
    
    void Newpoint(int &k,int last,int l,int r,int x,int qwq)
    {
    	k=++pool;
    	b[k]=b[last];
    	if(l==r)
    	{
    		Last(k)=qwq;
    		return;
    	}
    	int mid=l+r>>1;
    	if(mid>=x)
    		Newpoint(l(k),l(last),l,mid,x,qwq);
    	else
    		Newpoint(r(k),r(last),mid+1,r,x,qwq);
    	Last(k)=min(Last(l(k)),Last(r(k)));
    }
    
    void init()
    {
    	scanf("%d %d",&n,&m);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i]),a[i]=a[i]>n?n:a[i];
    	for (int i=1;i<=n;i++)
    		Newpoint(rt[i],rt[i-1],0,n,a[i],i);
    }
    
    int Query(int k,int l,int r,int x)
    {
    	if(l==r)
    		return l;
    	int mid=l+r>>1;
    	if(Last(l(k))>=x)
    		return Query(r(k),mid+1,r,x);
    	return Query(l(k),l,mid,x);
    }
    
    void work()
    {
    	int x,y;
    	while(m--)
    	{
    		scanf("%d %d",&x,&y);
    		printf("%d
    ",Query(rt[y],0,n,x));
    	}
    }
    
    int main()
    {
    	init();
    	work();
    	return 0;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    asp.net自带的异步刷新控件使用
    C#反射之创建对象实例
    用httpHandler实现简易ajax框架
    在配置文件中使用相对路径连接数据库文件
    C# 扩展方法
    JavaScript动态创建元素(老帖新发)
    为所有类型扩展一个深拷贝方法
    C#反射之获取程序集信息
    枚举类型的位运算
    SQL2005数据库还原到SQL2000的方法
  • 原文地址:https://www.cnblogs.com/With-penguin/p/12839479.html
Copyright © 2011-2022 走看看