Rmq Problem bzoj-3339||mex bzoj-3585

题目大意:给定一个长度为n的数列a,多次讯问区间l,r中最小的不属于集合{$A_l,A_{l+1}...A_r$}的非负整数。

注释:n,q$\le$200,000 ; 0$\le A_i \le$200,000 ; $A_i$均为非负整数,1<=l<=r<=n,l和r均为正整数。

想法:网上很多其他的算法(suika:离线+莫队,WinnieChen:在线权值线段树),我们来聊一聊离线加线段树。

  首先,我们将询问离线,按左端点为第一关键字排序。

  紧接着,预处理一点东西:暴力求出1~i之间的答案,以及每一个数位置pos的数a[pos]右边第一个等于a[pos]的数,它的位置我们记为nxt[pos]。

  然后,我们从左往右扫,对于当前数a[l],对于l+1到nxt[l]-1之间的数都需要进行区间赋值乘a[l],这个操作我们用线段树完成。如果当前节点还是一个被查询区间的左端点的话,我们直接输出右端点对应的mex即可。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <algorithm>
#define lson pos<<1
#define rson pos<<1|1
#define inf 0x7fffffff
using namespace std;
int n,m,k=0;
int a[200005],sg[200005],ans[200005],next[200005],last[200005];
int ls[600005],rs[600005],mn[600005];
bool mark[200001];
struct data{int l,r,id;}q[200005];
bool cmp(data a,data b)
{return a.l<b.l;}
void build(int l,int r,int pos)
{
ls[pos]=l;
rs[pos]=r;
mn[pos]=inf;
if(l==r)
{
mn[pos]=sg[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,lson);build(mid+1,r,rson);
}
void pushdown(int pos)
{
int l=ls[pos],r=rs[pos];
if(l==r)return;
mn[lson]=min(mn[pos],mn[lson]);
mn[rson]=min(mn[pos],mn[rson]);
}
int ask(int pos,int x)
{
if(mn[pos]!=inf)pushdown(pos);
int l=ls[pos],r=rs[pos];
if(l==r)return mn[pos];
int mid=(l+r)>>1;
if(x<=mid)return ask(lson,x);
return ask(rson,x);
}
void update(int pos,int x,int y,int val)
{
if(mn[pos]!=inf)pushdown(pos);
int l=ls[pos],r=rs[pos];
if(l==x&&y==r){mn[pos]=min(mn[pos],val);return;}
int mid=(l+r)>>1;
if(y<=mid)update(lson,x,y,val);
else if(x>mid)update(rson,x,y,val);
else
{
update(lson,x,mid,val);
update(rson,mid+1,y,val);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
mark[a[i]]=1;
if(a[i]==k)
while(mark[k])k++;
sg[i]=k;
}
build(1,n,1);
for(int i=n;i>0;i--)
next[i]=last[a[i]],last[a[i]]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+m+1,cmp);
int now=1;
for(int i=1;i<=m;i++)
{
while(now<q[i].l)
{
if(!next[now])next[now]=n+1;
update(1,now,next[now]-1,a[now]);
now++;
}
ans[q[i].id]=ask(1,q[i].r);
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}

小结:对着hzwer学长写的动态开点,感觉爆炸。注意pushdown的时候要记得删除之前的标记。

[bzoj3339]Rmq Problem||[bzoj3585]mex_线段树的更多相关文章

  1. CF803G-Periodic RMQ Problem【离散化,线段树,ST表】

    正题 题目链接:https://www.luogu.com.cn/problem/CF803G 题目大意 一个长度为\(n\)的序列\(a\)复制\(k\)份连接,要求支持 区间赋值 区间查询最小值 ...

  2. BZOJ 3489 A simple rmq problem(可持久化线段树)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489 题意:一个数列.每次询问一个区间内出现一次的最大的数字是多少. 思路:设la ...

  3. hihocode 1077 : RMQ问题再临-线段树

    #1077 : RMQ问题再临-线段树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到:小Hi给小Ho出了这样一道问题:假设整个货架上从左到右摆放了N种商品,并 ...

  4. Hihocoder #1077 : RMQ问题再临-线段树(线段树:结构体建树+更新叶子往上+查询+巧妙使用father[]+线段树数组要开大4倍 *【模板】)

    #1077 : RMQ问题再临-线段树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到:小Hi给小Ho出了这样一道问题:假设整个货架上从左到右摆放了N种商品,并 ...

  5. poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...

  6. 2018 ACMICPC上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节)

    2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节) 链接:https://ac.nowcoder.co ...

  7. [BZOJ3339] Rmq Problem(线段树)

    传送门 这个题的方法好像很多啊 1.莫队暴力 2.线段树 + 离线处理 先预处理出sg[i]表示前i个数的sg值,next[i]表示i的下一位置在哪里,如果后面再没有i,那么next[i] = n + ...

  8. BZOJ3339 Rmq Problem

    [bzoj3339]Rmq Problem Description Input Output Sample Input 7 5 0 2 1 0 1 3 2 1 3 2 3 1 4 3 6 2 7 Sa ...

  9. BZOJ3489 A simple rmq problem 【可持久化树套树】*

    BZOJ3489 A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一 ...

随机推荐

  1. 不使用c的任何库函数 实现字符串到整数的转换 整数到字符串的转换

    转载请标明出处:http://www.cnblogs.com/NongSi-Net/p/6805844.html 今天主要总结下:完成编程: 1.除printf函数之外,不用任何c语言库函数,实现将字 ...

  2. nginx 反向跳转

    语法规则: location [=|~|~*|^~] /uri/ { … }= 开头表示精确匹配^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可.nginx不对url做编码,因此请 ...

  3. H5 触摸事件

    HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应用实战性不是太强,所以在这里基本省略,咱们只分享应用广泛兼容不错的事件,日后随着兼容情况提升以后再陆续添加分享.今天为大家介绍的事件主 ...

  4. Java 编译与反编译

    编程语言 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language).编程语言(Programming Language)分为低级语言(Low-level Lang ...

  5. zb的生日-------搜索 和 动态规划

    简单的贪心算法 : http://love-oriented.com/pack/P01.html  说实话 我是喜欢 动态规划的.......但是省赛迫在眉睫 , 只好先 学 搜索了  ,  赶紧   ...

  6. Google广告屏蔽插件adBlock

    今天在博客园写博客的时候发现莫名其妙的在右侧被植入了广告,询问了管理员得知存在以下几种可能: 1.电信网络供应商劫持网页,植入广告 2.ADSafe(是一款去除广告的软件,效果很不错) 但经过最终排除 ...

  7. Excel工作常用(一)-生成序列与删除空行

    整理一些工作中,本人经常用到的一些Excel操作 1.自动生成序列 [注]选择 第一格 和 第二格 之后,在右下角出现十字的时候,在往下拉 2.删除空行 方式一,先找出所有空行,在删 [缺点]数据多的 ...

  8. asp.net——根据时间,显示内容

    题目: 在VS 2010中建立一个网站,命名为Lab5_1,建立时注意项目文件夹的存放位置.根据当前时间,在页面上显示早上好或下午好或晚上好,并显示相应的不同图片. 体验: 一开始看到这个题目的时候, ...

  9. Jupyter(Ipython) Notebook 入门

    upyter Notebook(此前被称为 IPython notebook)是一个交互式笔记本,支持运行 40 多种编程语言. 一般用来编写漂亮的交互式文档. 文学编程的读者不是机器,而是人. 我们 ...

  10. SQL基本操作——函数

    函数的类型:在 SQL 中,基本的函数类型和种类有若干种.函数的基本类型是:Aggregate 函数.Scalar 函数. Aggregate 函数:操作面向一系列的值,并返回一个单一的值,下面是SQ ...