BZOJ3339&&3585 Rmq Problem&&mex
BZOJ3339&&3585:Rmq Problem&&mex
Description
有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。
Input
第一行n,m。
第二行为n个数。
从第三行开始,每行一个询问l,r。
Output
一行一个数,表示每个询问的答案。
Sample Input
5 5
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5
Sample Output
1
2
3
0
3
HINT
数据规模和约定
对于\(100%\)的数据:
\(1\leq n,m\leq200000\)
\(0\leq a_i\leq10^9\)
\(1\leq l,r\leq n\)
对于\(30%\)的数据:
\(1\leq n,m \leq1000\)
题解
先离散化,注意补充上每个数\(+1\)和\(0\)。
离线所有询问,按左端点\(l\)排序。
不难得到\([1,i]\)的答案
考虑已知区间\([l,r]\)的答案,如何得到区间\([l+1,r]\)的答案
这样其实是删除了\(a[l]\),\(nxt[l]\)表示下一个\(a[l]\)出现的位置,所以删除\(a[l]\)影响了\([l+1,l+1]\)到\([l+1,nxt[l]-1]\)这些区间。这些区间的\(mex\)都要对\(a[l]\)取\(min\)。
区间取\(min\),典型线段树操作。叶子节点的\(ma\)是值,其余节点\(ma\)存区间取\(min\)标记。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <cmath>
#include <string>
#define abs(x) ((x) < 0 ? -1 * (x) : (x))
template <class T>
inline void read(T &x)
{
x = 0;char ch = getchar(), c = ch;
while(ch < '0' || ch > '9') c = ch, ch = getchar();
while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
if(c == '-') x = -x;
}
inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;}
const int INF = 0x3f3f3f3f;
const int MAXN = 400000 + 10;
int n,q,num[MAXN],tong[MAXN],nxt[MAXN];
struct Q
{
int l,r,rank;
}a[MAXN];
bool cmp(Q a, Q b)
{
return a.l < b.l;
}
struct Node
{
int ma, lazy, l, r;
Node(){ma = INF;lazy = -1;}
}node[MAXN << 3];
void pushdown(int o)
{
node[o << 1].ma = min(node[o << 1].ma, node[o].ma);
node[o << 1 | 1].ma = min(node[o << 1 | 1].ma, node[o].ma);
}
void modify(int ll, int rr, int k, int o = 1, int l = 1, int r = n)
{
pushdown(o);node[o].l = l, node[o].r = r;
if(ll <= l && rr >= r)
{
node[o].ma = min(node[o].ma, k);
node[o].lazy = k;
return;
}
int mid = (l + r) >> 1;
if(mid >= ll) modify(ll, rr, k, o << 1, l, mid);
if(mid < rr) modify(ll, rr, k, o << 1 | 1, mid + 1, r);
return;
}
int ask(int p, int o = 1, int l = 1, int r = n)
{
pushdown(o);
if(l == r && p == l) return node[o].ma;
int mid = (l + r) >> 1;
if(p <= mid) return ask(p, o << 1, l, mid);
else return ask(p, o << 1 | 1, mid + 1, r);
}
int ans[MAXN];
//lisanhua
int tmp[MAXN], cnt[MAXN], val[MAXN], tot;
bool cmpp(int a, int b)
{
return tmp[a] < tmp[b];
}
int main()
{
read(n), read(q);
for(int i = 1;i <= n;++ i)
read(num[i]), tmp[i] = num[i], cnt[i] = i;
std::sort(cnt + 1, cnt + 1 + n, cmpp);num[0] = -1;
for(int i = 1;i <= n;++ i)
{
if(tmp[cnt[i - 1]] != tmp[cnt[i]])
{
++ tot;
if(tmp[cnt[i]] - tmp[cnt[i - 1]] > 1) val[tot] = num[cnt[i - 1]] + 1, ++ tot;
num[cnt[i]] = tot;
val[tot] = tmp[cnt[i]];
}
else num[cnt[i]] = tot;
}
val[++ tot] = tmp[cnt[n]] + 1;
for(int i = 1;i <= q;++ i)
read(a[i].l), read(a[i].r), a[i].rank = i;
std::sort(a + 1, a + 1 + q, cmp);
int p = 0;
for(int i = 1;i <= n;++ i)
if(num[i] == p)
{
tong[p] = 1;
while(tong[p]) ++ p;
modify(i, i, p);
}
else tong[num[i]] = 1, modify(i, i, p);
memset(tong, 0, sizeof(tong));
for(int i = n;i >= 1;-- i)
if(!tong[num[i]]) nxt[i] = n + 1, tong[num[i]] = i;
else nxt[i] = tong[num[i]], tong[num[i]] = i;
int now = 1;
for(int i = 1;i <= q;++ i)
{
while(now < a[i].l)
{
modify(now, nxt[now] - 1, num[now]);
++ now;
}
ans[a[i].rank] = ask(a[i].r);
}
for(int i = 1;i <= q;++ i) printf("%d\n", val[ans[i]]);
return 0;
}
BZOJ3339&&3585 Rmq Problem&&mex的更多相关文章
- 分块+莫队||BZOJ3339||BZOJ3585||Luogu4137||Rmq Problem / mex
题面:P4137 Rmq Problem / mex 题解:先莫队排序一波,然后对权值进行分块,找出第一个没有填满的块,直接for一遍找答案. 除了bzoj3339以外,另外两道题Ai范围都是1e9. ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- 【bzoj3339】Rmq Problem
[bzoj3339]Rmq Problem Description Input Output Sample Input 7 50 2 1 0 1 3 21 32 31 43 62 7 Sample ...
- 【Luogu4137】Rmq Problem/mex (莫队)
[Luogu4137]Rmq Problem/mex (莫队) 题面 洛谷 题解 裸的莫队 暴力跳\(ans\)就能\(AC\) 考虑复杂度有保证的做法 每次计算的时候把数字按照大小也分块 每次就枚举 ...
- P4137 Rmq Problem / mex (莫队)
题目 P4137 Rmq Problem / mex 解析 莫队算法维护mex, 往里添加数的时候,若添加的数等于\(mex\),\(mex\)就不能等于这个值了,就从这个数开始枚举找\(mex\): ...
- 洛谷 P4137 Rmq Problem /mex 解题报告
P4137 Rmq Problem /mex 题意 给一个长为\(n(\le 10^5)\)的数列\(\{a\}\),有\(m(\le 10^5)\)个询问,每次询问区间的\(mex\) 可以莫队然后 ...
- BZOJ 3339 && luogu4137 Rmq Problem / mex(莫队)
P4137 Rmq Problem / mex 题目描述 有一个长度为n的数组{a1,a2,-,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入输出格式 输入格式: 第一行n,m. ...
- [bzoj3585] Rmq Problem / mex
[bzoj3585] Rmq Problem / mex bzoj luogu 看上一篇博客吧,看完了这个也顺理成章会了( (没错这篇博客就是这么水) #include<cstdio> # ...
- BZOJ3339:Rmq Problem & BZOJ3585 & 洛谷4137:mex——题解
前者:https://www.lydsy.com/JudgeOnline/problem.php?id=3339 后者: https://www.lydsy.com/JudgeOnline/probl ...
随机推荐
- JavaScript基础的一些小总结
一.js变量 1.变量声明: var 关键字来进行变量声明 变量是弱类型 1.数字 2.小数 3.boolean 4.字符串 4.字符 验证数据类型:1.整数,小数是numbe ...
- ImportError: cannot import name webdriver解决方案
在sublime写一个Python程序的时候,使用from selenium import webdriver,在run的时候却出现ImportError: cannot import nam ...
- P1919 【模板】A*B Problem升级版 /// FFT模板
题目大意: 给定l,输入两个位数为l的数A B 输出两者的乘积 FFT讲解 这个讲解蛮好的 就是讲解里面贴的模板是错误的 struct cpx { double x,y; cpx(double _x= ...
- centos 7 开机启动服务项优化
1. 使用 systemctl list-unit-files 可以查看启动项 systemctl list-unit-files | grep enable 过滤查看启动项如下 abrt-ccpp. ...
- spring:bean的细节之三种创建Bean对象的方式
<!--创建Bean的三种方式--><!--第一种方式,使用默认构造函数创建 在spring的配置文件中使用bean标签,配以id和class属性之后,且没有属性和标签时. 采用的就 ...
- 【学术篇】状态压缩动态规划——POJ3254/洛谷1879 玉米田Corn Field
我要开状压dp的坑了..直播从入门到放弃系列.. 那就先拿一道状压dp的水题练练手吧.. 然后就找到了这一道..这道题使我清醒地认识到阻碍我的不是算法,而是视力= = 传送门: poj:http:// ...
- Mysql 数据库crash恢复
之前搭建的ghost博客比较坑,修改comment之后重启数据丢了,对node不熟悉,所以就切换回到wordpress了. 回滚快照之后发现数据库crash了,提示如下信息 2016-06-15 23 ...
- 【JZOJ3400】旅行
description 从前有一位旅者,他想要游遍天下所有的景点.这一天他来到了一个神奇的王国:在这片土地上,有n个城市,从1到n进行编号.王国中有m条道路,第i条道路连接着两个城市ai,bi,由于年 ...
- CSS - 定位相关
定位 (position) 1. 相对定位 (relative) 相对于元素原来的位置进行移动 2. 绝对定位 (absolute) 如果父级元素中有相对定位属性, 则参照父级元素进行定位, 默认参照 ...
- DuiLib学习笔记2.写一个简单的程序
我们要独立出来自己创建一个项目,在我们自己的项目上加皮肤这才是初衷.我的新建项目名为:duilibTest 在duilib根目录下面有个 Duilib入门文档.doc 我们就按这个教程开始入门 首先新 ...