• 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;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    需求获取常见的方法是进行客户访谈,结合你的实践谈谈会遇到什么问题,你是怎么解决的?
    软件工程导论 习题五
    软件工程导论 习题四
    软件工程导论 习题三
    软件工程导论 习题二(1.2.3.5)
    软件工程导论 习题一
    面向对象分析方法和面向过程分析方法的区别
    几大开发模型区别与联系
    项目总结
    关于需求
  • 原文地址:https://www.cnblogs.com/With-penguin/p/12839479.html
Copyright © 2020-2023  润新知