题目描述

输入

输出

样例输入

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 ;
}

最新文章

  1. Firebug调试js代码
  2. CF449C Jzzhu and Apples (筛素数 数论?
  3. Java接口与实例化
  4. Direct3D11学习:(七)绘图基础——彩色立方体的绘制
  5. 在JS函数中执行C#中的函数、字段
  6. 20160808_Qt570安装
  7. linux常用命令--ps、netstat、find
  8. NDK开发之日志打印
  9. 基于visual Studio2013解决C语言竞赛题之0506选择排序
  10. AngularJS的依赖注入方式
  11. Linux基础:xargs命令
  12. 实验二Java面向对象程序设计实验报告(2)
  13. 函数语法:Js之on和addEventListener的使用与不同
  14. Win server 2012 +IIS8.0下安装SSL证书
  15. 使用rander() 将后台的数据传递到前台界面显示出来
  16. Hadoop错误集:Could not find the main class: org.apache.hadoop.*
  17. Windows XP系统服役13年今正式退休
  18. 关于SpringCloud微服务架构概念的一点理解
  19. C++14尝鲜:Generic Lambdas(泛型lambda)
  20. CodeForces 513A Game (水题,博弈)

热门文章

  1. IntelliJ IDEA 和 webstorm更换主题
  2. 转载 - Catalan数(卡特兰数)
  3. EXPLAIN sql优化方法(1) 添加索引
  4. 神奇的JAVA多态
  5. 洛谷—— P1041 传染病控制
  6. logistic regression model
  7. AIX下sort命令简介及使用
  8. 当前插入的线段能完整覆盖存在的几条线段 树状数组 HDU 5372 Segment Game
  9. PixelUtils:像素转换工具
  10. C#之简易猜数字游戏