1. 程式人生 > >BZOJ3339: Rmq Problem

BZOJ3339: Rmq Problem

print algo amp ali class ++ bzoj sizeof target

【傳送門:BZOJ3339】


簡要題意:

  給出一個長度為n的數列,有m個詢問,每個詢問輸入l,r,求出l到r之間沒出現過的最小自然數


題解:

  同BZOJ3585


參考代碼:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct question
{
    int l,r,id,d;
}q[210000];
int
belong[210000],L[1100],R[1100],block; bool cmp1(question n1,question n2) { if(belong[n1.l]<belong[n2.l]) return true; if(belong[n1.l]>belong[n2.l]) return false; if(n1.r<n2.r) return true; if(n1.r>n2.r) return false; return false; } bool cmp2(question n1,question n2) {
return n1.id<n2.id; } int a[210000],d[210000]; int sum[1100]; void del(int x) { d[x]--; if(d[x]==0) sum[belong[x]]--; } void add(int x) { d[x]++; if(d[x]==1) sum[belong[x]]++; } int solve() { for(int i=1;i<=block;i++) { if(sum[i]!=R[i]-L[i]+1) {
for(int j=L[i];j<=R[i];j++) { if(d[j]==0) return j; } } } } int main() { int n,m; scanf("%d%d",&n,&m); block=int(sqrt(n)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]);a[i]++; if(a[i]>n) a[i]=n; int t=(i-1)/block+1; belong[i]=t; if(L[t]==0) R[t-1]=i-1,L[t]=i; } R[belong[n]]=n; for(int i=1;i<=m;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i; sort(q+1,q+m+1,cmp1); int l=1,r=0; memset(d,0,sizeof(d)); for(int i=1;i<=m;i++) { while(l<q[i].l) del(a[l]),l++; while(l>q[i].l) l--,add(a[l]); while(r<q[i].r) r++,add(a[r]); while(r>q[i].r) del(a[r]),r--; q[i].d=solve()-1; } sort(q+1,q+m+1,cmp2); for(int i=1;i<=m;i++) printf("%d\n",q[i].d); return 0; }

BZOJ3339: Rmq Problem