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;
    }
    
    由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
  • 相关阅读:
    ACM ICPC 2008–2009 NEERC MSC A, B, C, G, L
    POJ 1088 滑雪 DP
    UVA 11584 最短回文串划分 DP
    POJ 2531 Network Saboteur DFS+剪枝
    UVa 10739 String to Palindrome 字符串dp
    UVa 11151 Longest Palindrome 字符串dp
    UVa 10154 Weights and Measures dp 降维
    UVa 10271 Chopsticks dp
    UVa 10617 Again Palindrome 字符串dp
    UVa 10651 Pebble Solitaire 状态压缩 dp
  • 原文地址:https://www.cnblogs.com/With-penguin/p/12839479.html
Copyright © 2011-2022 走看看