题目描述

输入

输出

样例输入

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)的更多相关文章

  1. 【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 ...

  2. BZOJ3339&&3585 Rmq Problem&&mex

    BZOJ3339&&3585:Rmq Problem&&mex Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最 ...

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

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

  4. 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 ...

  5. 分块+莫队||BZOJ3339||BZOJ3585||Luogu4137||Rmq Problem / mex

    题面:P4137 Rmq Problem / mex 题解:先莫队排序一波,然后对权值进行分块,找出第一个没有填满的块,直接for一遍找答案. 除了bzoj3339以外,另外两道题Ai范围都是1e9. ...

  6. [bzoj3339]Rmq Problem||[bzoj3585]mex_线段树

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

  7. 「HAOI2011」Problem c

    「HAOI2011」Problem c 传送门 由于这道题本人讲得不好,可以参考这位dalao的博客 我可就直接上代码了... 参考代码: /*---------------------------- ...

  8. 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 ...

  9. loj2353. 「NOI2007」 货币兑换

    loj2353. 「NOI2007」 货币兑换 链接 https://loj.ac/problem/2353 思路 题目不重要,重要的是最后一句话 提示 输入文件可能很大,请采用快速的读入方式. 必然 ...

随机推荐

  1. 0926mysql中MRR的用法

    转自 http://blog.itpub.net/22664653/viewspace-1673682  [MySQL]MySQL5.6新特性之Multi-Range Read 2015-05-27 ...

  2. Shallow Heap 和 Retained Heap的区别

    http://blog.csdn.net/a740169405/article/details/53610689 Shallow Heap 和 Retained Heap的区别 https://i.c ...

  3. Udp发送端和接收端

    //UdpReceive.java /* 定义udp的接收端. 思路: 1.定义udpSocket服务.一般会监听一个端口,事实上就是这个接收网络应用程序定义一个数字标示. 2.定义一个数据包.用来存 ...

  4. ZOJ 3494

    超级神奇有趣题. AC自动机+数位DP.其实,数位DP在处理含有某些数字时特别不好处理,应该把它倒转为求不含有.这道题把数位DP+AC自动机结合起来,实在是很巧妙,把数字变为串来处理,强大! 要使用A ...

  5. FPGA 浮点单元设计

    浮点数在内存中的存放格式例如以下: 地址 +0 +1 +2 +3 内容 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM 这里 S 代表符号位,1是负,0是正 E 偏移1 ...

  6. 【cl】sikuli下载安装

    前提条件: 1.请确保你已经安装java 6 JRE 32位版本(如果是java 7 或者是64位JRE 那是不被支持的) 2.请确定你已经卸载的先前的sikuli版本(尤其是0.10.x版本) 3. ...

  7. 《Head First 设计模式》学习笔记——复合模式

    模型-视图-控制器(MVC模式)是一种很经典的软件架构模式.在UI框架和UI设计思路中扮演着很重要的角色.从设计模式的角度来看,MVC模式是一种复合模式.它将多个设计模式在一种解决方式中结合起来,用来 ...

  8. TCP三次握手及关闭时的2MSL分析

    TCP/IP三次握手四次挥手,是非常重要的,这个链接与关闭过程也是非常easy的.但为什么是三次握手?以及为什么要等待2MSL的状态?大部分人或许听到这个问题就蒙了.这篇博客就综合<TCP/IP ...

  9. 彻底弄懂px em rem

    国内的设计师大都喜欢用px,而国外的网站大都喜欢用em和rem,那么三者有什么区别,又各自有什么优劣呢? PX特点 1. IE无法调整那些使用px作为单位的字体大小: 2. 国外的大部分网站能够调整的 ...

  10. Prism学习(1)---前期准备

    本文摘取自Gene's Blog的博客园文章,版权归Gene's Blog,仅供个人学习参考.转载请标明原作者Gene's Blog. 在学习Prism框架之前,我预先写了一个非常简单的计算器解决方案 ...