「BZOJ3339」Rmq Problem(5366)
题目描述

输入

输出

样例输入
7 5
0 2 1 0 1 3 2
1 3
2 3
1 4
3 6
2 7
提示

这个题说来也挺有意思的
当时集训的时候遇到了一道类似的题,但是题意与此不同,我太菜了,理解成了这个题233结果爆零(蒟蒻咆哮:“唉我AC呢!?”)
所以就把以前写的码翻了出来,交了上去,果然A了2333
当时的写法是这样的:
首先处理出每个数下一次出现的位置,这样每个数字就处理成了 这段区间内这个数没有出现过,数量是O(n)级别的
那么一个询问区间的答案就是所有套在它外面的不出现区间的最小值
具体实现就是首先离线,将“询问区间”和“不出现区间”在一起按照左端点排序,如果相同则优先处理“不出现区间”
此时维护一个线段树,位置表示的是区间的右端点,这个位置上存的是:l小于等于当前扫到的L,且以这个位置为r的区间中数最小的是啥
那么如果扫到了一个提问,那么答案就是(R,N)这个区间内最小值
当时写码的时候有点蒙圈,实际上好像写个单点修改就好了?
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200005
#define inf n+1
using namespace std;
int a[maxn],nxt[maxn],top;
int n,m,s[maxn*],tag[maxn*];
struct line{
int l,r,x,o;
}q[maxn*];
bool cmp(line A,line B){if(A.l!=B.l)return A.l<B.l;else return A.o<B.o;}
int ans[maxn];
void build(int x,int l,int r){
s[x]=tag[x]=inf;
if(l==r)return;
int mid=(l+r)/;
build(x+x,l,mid);
build(x+x+,mid+,r);
}
void pushdown(int x,int l,int r){
if(l==r){
tag[x]=inf;
return;
}
s[x+x]=min(s[x+x],tag[x]);
tag[x+x]=min(tag[x+x],tag[x]);
s[x+x+]=min(s[x+x+],tag[x]);
tag[x+x+]=min(tag[x+x+],tag[x]);
tag[x]=inf;
return;
}
void add(int x,int l,int r,int L,int R,int k){
if(l==L&&r==R){
s[x]=min(s[x],k);
tag[x]=min(tag[x],k);
return;
}
pushdown(x,l,r);
int mid=(l+r)/;
if(R<=mid)add(x+x,l,mid,L,R,k);
else if(L>mid)add(x+x+,mid+,r,L,R,k);
else add(x+x,l,mid,L,mid,k),add(x+x+,mid+,r,mid+,R,k);
s[x]=min(s[x+x],s[x+x+]);
}
int query(int x,int l,int r,int L,int R){
if(l==L&&r==R)return s[x];
pushdown(x,l,r);
int mid=(l+r)/;
if(R<=mid)return query(x+x,l,mid,L,R);
else if(L>mid)return query(x+x+,mid+,r,L,R);
else return min(query(x+x,l,mid,L,mid),query(x+x+,mid+,r,mid+,R));
}
int main(){
scanf("%d%d",&n,&m);
build(,,n);
nxt[]=n+;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
nxt[i]=n+;
}
nxt[n+]=n+;
for(int i=n;i>=;i--){
if(nxt[a[i]]-i->){
q[++top].o=;
q[top].l=i+;
q[top].r=nxt[a[i]]-;
q[top].x=a[i];
}
nxt[a[i]]=i;
}
for(int i=;i<=n+;i++)
if(nxt[i]->){
q[++top].o=;
q[top].l=;
q[top].r=nxt[i]-;
q[top].x=i;
}
for(int i=,l,r;i<=m;i++){
scanf("%d%d",&l,&r);
q[++top].o=;
q[top].l=l;
q[top].r=r;
q[top].x=i;
}
sort(q+,q++top,cmp);
for(int i=;i<=top;i++){
if(q[i].o==)
add(,,n,q[i].r,q[i].r,q[i].x);
else{
int A=query(,,n,q[i].r,n);
ans[q[i].x]=A;
}
}
for(int i=;i<=m;i++)printf("%d\n",ans[i]);
return ;
}
不过这个题还有在线的主席树做法
我们维护一个线段树,以数值为位置,里面存的是目前为止这个数最近一次出现的位置
那么询问一个区间l r,就找r之前都加入了的线段树,找里面出现位置小于l且最小的数
这个可以通过在线段树上跳跃实现,具体看代码吧
这是我写(抄)的第一个主席树,感觉还是不太明了的样子。。。இ௰இ
#include<cstdio>
#include<algorithm>
#define maxn 200005
using namespace std;
int n,m,cnt;
int rt[maxn],a[maxn],b[maxn];
struct tree{
int l,r,Min;
}t[*maxn];
int insert(int K,int X,int I,int l,int r){
t[++cnt]=t[K];
K=cnt;
if(l==r){
t[K].l=t[K].r=;
t[K].Min=I;
return cnt;
}
int mid=(l+r)>>;
if(X<=mid)
t[K].l=insert(t[K].l,X,I,l,mid);
else
t[K].r=insert(t[K].r,X,I,mid+,r);
t[K].Min=min(t[t[K].l].Min,t[t[K].r].Min);
return K;
}
int query(int k,int X,int l,int r){
if(l==r)return l;
int mid=(l+r)>>;
if(t[t[k].l].Min<X)
return query(t[k].l,X,l,mid);
else return query(t[k].r,X,mid+,r);
}
int main(){
scanf("%d%d",&n,&m);
rt[]=;
t[]=(tree){,,};
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]<=n)
rt[i]=insert(rt[i-],a[i],i,,n);
else rt[i]=rt[i-];
}
for(int i=,l,r;i<=m;i++){
scanf("%d%d",&l,&r);
printf("%d\n",query(rt[r],l,,n));
}
return ;
}
「BZOJ3339」Rmq Problem(5366)的更多相关文章
- 【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 ...
- BZOJ3339&&3585 Rmq Problem&&mex
BZOJ3339&&3585:Rmq Problem&&mex Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最 ...
- BZOJ3339:Rmq Problem & BZOJ3585 & 洛谷4137:mex——题解
前者:https://www.lydsy.com/JudgeOnline/problem.php?id=3339 后者: https://www.lydsy.com/JudgeOnline/probl ...
- 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 ...
- 分块+莫队||BZOJ3339||BZOJ3585||Luogu4137||Rmq Problem / mex
题面:P4137 Rmq Problem / mex 题解:先莫队排序一波,然后对权值进行分块,找出第一个没有填满的块,直接for一遍找答案. 除了bzoj3339以外,另外两道题Ai范围都是1e9. ...
- [bzoj3339]Rmq Problem||[bzoj3585]mex_线段树
Rmq Problem bzoj-3339||mex bzoj-3585 题目大意:给定一个长度为n的数列a,多次讯问区间l,r中最小的不属于集合{$A_l,A_{l+1}...A_r$}的非负整数. ...
- 「HAOI2011」Problem c
「HAOI2011」Problem c 传送门 由于这道题本人讲得不好,可以参考这位dalao的博客 我可就直接上代码了... 参考代码: /*---------------------------- ...
- loj#2483. 「CEOI2017」Building Bridges 斜率优化 cdq分治
loj#2483. 「CEOI2017」Building Bridges 链接 https://loj.ac/problem/2483 思路 \[f[i]=f[j]+(h[i]-h[j])^2+(su ...
- loj2353. 「NOI2007」 货币兑换
loj2353. 「NOI2007」 货币兑换 链接 https://loj.ac/problem/2353 思路 题目不重要,重要的是最后一句话 提示 输入文件可能很大,请采用快速的读入方式. 必然 ...
随机推荐
- Django(七)
一.ModelForm操作及验证 1.class Meta:class Meta: #注意以下字段不能加逗号 model = models.UserInfo #这里的all代指所用的字段,也可以是一个 ...
- MYSQL 源码解读系列 [线程池。。] ----dennis的博客
http://blog.sina.com.cn/s/articlelist_1182000643_0_1.html
- 零基础学python-2.16 列表解析
这一节聊聊强大的列表解析 主要就是在一行里面赋值给列表 以下我们举两个样例: 上面的样例我们引入了range函数,他主要作用是在一定范围里面取整数值 我来解释一下中括号中面的那一句:x**2 for ...
- win server 2008 r2 iis+php 500错误内部服务器错误。
今天遇到一个错误是iis 500错误,由于server是别人负责的.查看日志没什么异常,就发如今任务日志里发现有一段时间间隔没有记录.一開始不知道为什么.之后日志里就都是500错误了,在iis哪里配置 ...
- HDU3117-Fibonacci Numbers(矩阵高速幂+log)
题目链接 题意:斐波那契数列,当长度大于8时.要输出前四位和后四位 思路:后四位非常easy,矩阵高速幂取模,难度在于前四位的求解. 已知斐波那契数列的通项公式:f(n) = (1 / sqrt(5 ...
- sqlite3树形结构遍历效率对照測试
sqlite3树形结构遍历效率对照測试 一.缘起 项目数据结构:本人从事安防行业,视频监控领域.项目中会遇到监控点位的组织机构划分.暂时划分的巡逻点位等.这些相机点位.连同组织机构,它们在逻辑关系上构 ...
- 虚拟机window7与主机之间文件复制设置
一.需要安装VMware Tools 选中虚拟机>虚拟机>安装VMware Tools 一直点击下一步直至完成 二.设置文件共享 选定实体机需要共享给虚拟机的文件夹,并为该共享起一个名称. ...
- UVA 10888 - Warehouse(二分图完美匹配)
UVA 10888 - Warehouse option=com_onlinejudge&Itemid=8&page=show_problem&category=562& ...
- Java基础:异常捕获顺序
转载请注明出处:jiq•钦's technical Blog public voidtestException(){ int a[] = {1,2,3};int q = 0; try{ for(int ...
- bzoj4247: 挂饰(背包)
4247: 挂饰 题目:传送门 题解: 看完题目很明显的一道二维背包(一开始还推错了) 设f[i][j]表示前i个挂饰选完(可以有不选)之后还剩下j个挂钩的最大值(j最多贡献为n) 那么f[i][j] ...