1. 程式人生 > >NKOJ 4254 區間MEX (線段樹)

NKOJ 4254 區間MEX (線段樹)

P4254區間MEX

問題描述

給你一個長度為n的數列,元素編號1到n,第i個元素值為Ai。現在有m個形如(L,R)的提問,你需要回答出區間[L,R]的mex值。即求出區間[L,R]中沒有出現過的最小的非負整數。

輸入格式

第一行,兩個整數n和m
第二行,n個空格間隔的整數,表示數列A
接下來m行,每行兩個整數L,R,表示一次詢問

輸出格式

m行,每行一個整數,表示對應詢問的答案。

樣例輸入

7 5
0 2 1 0 1 3 2
1 3
2 3
1 4
3 6
2 7

樣例輸出

3
0
3
2
4

提示

1<=n,m<=200000
0<=Ai<=200000
1<=L<=R<=n

由於沒有修改,可以考慮離線演算法。先將詢問按照左端點排序。

S[i]表示區間[1,i]MEX,容易發現S[i]單調不降,並且可以O(n)的處理出來S陣列。那麼左端點為1的詢問都可以處理,然後考慮如何處理左端點為2時

考慮刪掉A[1]S陣列的影響,那麼令x=A[1],那麼S[x]以後肯定不會受到影響,而對於x之前的S[k]

如果S[k]>A[i],那麼S[k]=A[i],否則不變

那麼區間修改用線段樹來維護,按照左端點升序討論即可。

程式碼:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#define N 200005
#define M 2000005
#define min(a,b) ((a>b)?(b):(a))
using namespace std;
struct node{int id,l,r,ans;}Q[N];
bool cmp(node a,node b)
{return a.l<b.l;}
bool ccp(node a,node b)
{return a.id<b.id;}
int n,m,A[N],B[N],NE[N],LA[N];
bool
mark[N]; int ls[M],rs[M],v[M],lazy[M],tot,rt; int BT(int x,int y) { int p=++tot; lazy[p]=-1; if(x<y) { int mid=x+y>>1; ls[p]=BT(x,mid); rs[p]=BT(mid+1,y); } else v[p]=B[x]; return p; } void PD(int p) { int l=ls[p],r=rs[p],d=lazy[p]; lazy[p]=-1; v[l]=min(v[l],d); v[r]=min(v[r],d); if(lazy[l]==-1)lazy[l]=d; else lazy[l]=min(lazy[l],d); if(lazy[r]==-1)lazy[r]=d; else lazy[r]=min(lazy[r],d); } void MD(int p,int l,int r,int x,int y,int d) { if(lazy[p]!=-1)PD(p); if(x<=l&&y>=r){lazy[p]=d;v[p]=min(v[p],d);return;} int mid=l+r>>1; if(x<=mid&&y>=l)MD(ls[p],l,mid,x,y,d); if(x<=r&&y>mid)MD(rs[p],mid+1,r,x,y,d); } int GA(int p,int l,int r,int k) { if(lazy[p]!=-1)PD(p); if(l==r)return v[p]; int mid=l+r>>1; if(k<=mid)return GA(ls[p],l,mid,k); return GA(rs[p],mid+1,r,k); } int main() { int i,x,y; scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%d",&A[i]); for(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);x=0; for(i=1;i<=n;i++) { mark[A[i]]=1; while(mark[x])x++; B[i]=x; } for(i=n;i>=1;i--) { if(!LA[A[i]])NE[i]=n+1; else NE[i]=LA[A[i]]; LA[A[i]]=i; } rt=BT(1,n);x=1;i=1; while(i<=m) { while(x<Q[i].l) { if(x+1<NE[x])MD(rt,1,n,x+1,NE[x]-1,A[x]); x++; } while(x==Q[i].l) { Q[i].ans=GA(rt,1,n,Q[i].r); i++; } } sort(Q+1,Q+m+1,ccp); for(i=1;i<=m;i++)printf("%d\n",Q[i].ans); }