BZOJ3339:Rmq Problem & BZOJ3585 & 洛谷4137:mex——题解

前者:https://www.lydsy.com/JudgeOnline/problem.php?id=3339

后者:

https://www.lydsy.com/JudgeOnline/problem.php?id=3585

https://www.luogu.org/problemnew/show/P4137

有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

题解大部分都是莫队分块,但是复杂度为O(n*sqrt(n))=5e2*2e5=1e8摸着良心说能过吗?

(莫队都是n=1e5的……然而慢点评测机也过不去,可能需要更小。)

参考:网上貌似就三篇的数据结构做法。

考虑数据结构吧,选择权值建主席树,每个节点记录当前区间的值在序列中出现位置的最小值。

这样查询的时候可以在r这棵树上找节点小于l的就行啦。

(如果小于,说明这段值域区间内有值不在序列区间内,否则全在,就需要考虑更大值。)

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=4e5+5;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int l,r,min;
}tr[N*20];
int rt[N],pool,n,m,q,b[N],a[N];
inline void LSH(){
    sort(b+1,b+m+1);
    m=unique(b+1,b+m+1)-b-1;
    for(int i=1;i<=n;i++)
    a[i]=lower_bound(b+1,b+m+1,a[i])-b;
}
void insert(int y,int &x,int l,int r,int p,int v){
    tr[x=++pool]=tr[y];
    if(l==r){
    tr[x].min=v;
    return;
    }
    int mid=(l+r)>>1;
    if(p<=mid)insert(tr[y].l,tr[x].l,l,mid,p,v);
    else insert(tr[y].r,tr[x].r,mid+1,r,p,v);
    tr[x].min=min(tr[tr[x].l].min,tr[tr[x].r].min);
}
int query(int x,int l,int r,int v){
    if(l==r)return l;
    int mid=(l+r)>>1;
    if(tr[tr[x].l].min<v)return query(tr[x].l,l,mid,v);
    else return query(tr[x].r,mid+1,r,v);
}
int main(){
    n=read(),q=read();
    b[++m]=0;
    for(int i=1;i<=n;i++){
    a[i]=b[++m]=read();
    b[++m]=a[i]+1;
    }
    LSH();
    for(int i=1;i<=n;i++)insert(rt[i-1],rt[i],1,m,a[i],i);
    for(int i=1;i<=q;i++){
    int l=read(),r=read();
    printf("%d\n",b[query(rt[r],1,m,l)]);
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/9009623.html

时间: 2024-08-05 16:15:52

BZOJ3339:Rmq Problem & BZOJ3585 & 洛谷4137:mex——题解的相关文章

bzoj3339 rmq problem (range mex query)

给一个长度为n的数列a,q个询问,每次询问一段区间的mex.(没有出现过的最小非负整数) 1<=n,q<=200000,0<=ai<=200000. 题解1 莫队 我们将权值分成根号块,记录每个权值的出现次数和每块内有多少权值出现过. 修改和询问就直接暴力做就行. 修改O(1),询问O(sqrt(n)),加在一起还是O((n+q)sqrt(n+q)). #include <iostream> #include <stdio.h> #include <s

bzoj3339 Rmq Problem

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3339 [题解] 业界偷懒. 突然发现好像可以主席树啊..然后就强行上了一波发现确实可以. 第i棵主席树维护[1...i]这个前缀内,某权值区间的"最小出现位置". 比如 2 3 0 1 那么在rt[4]这棵主席树中,[0,3]最小出现位置为1,是2在第1位:[0,1]最小出现位置为3,是0在第3位. 那么查询(x,y)我们查询rt[y]根据最小出现位置x来在主席树上二分走即可.

【莫队算法】【权值分块】bzoj3339 Rmq Problem

如题. #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 200001 #define BN 451 int n,m,a[N],b[N],sumv[BN],l[N],num[N],num2[N],Lim,siz[BN],anss[N]; struct Ask{int l,r,p;void Read(){scanf("%d%d",&am

洛谷 P1077 摆花 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1077 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列. 试编程计算,一共有多少种不同的摆花方案. 输入输出格式 输入格式

洛谷 P1082 同余方程 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1082 题目描述 求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入输出格式 输入格式: 输入只有一行,包含两个正整数 a, b,用一个空格隔开. 输出格式: 输出只有一行,包含一个正整数 x0,即最小正整数解.输入数据保证一定有解. 输入输出样例 输入样例#1: 3 10 输出样例#1: 7 说明 [数据范围]

洛谷 P1816 忠诚 题解

题目链接:https://www.luogu.org/problem/show?pid=1816 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财主还是对管家产生了怀疑.于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3-编号,然后不定时的问管家问题,问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题. 输入

洛谷 P1042 乒乓球 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1042 题目背景 国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及.其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役.华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响.在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些

洛谷 P1540 机器翻译 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1540 题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件 会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译:如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含

Tower /点的移动(洛谷 1632)题解

[问题描述] 平面上有N个整数坐标点.如果将点(x0,y0)移动到(x1,y1),则需要的代价为|x0-x1|+|y0-y1|.求使得K(K=1,…,N)个点在同一位置上最少需要的代价. [样例输入] 4     15 14    15 16    14 15     16 15 [样例输出] 0    2    3    4 [解题思路] 初看这道题,还以为是只能移动到有点的地方,即把别的点移动到一个点上,移动(k-1)个点所需要的最小代价,结果发现样例都过不去……接着分析了一下样例,发现样例