【bzoj3585】mex 线段树 mex,sg

Description

  有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

Input

  第一行n,m。
第二行为n个数。
从第三行开始,每行一个询问l,r。

Output

  一行一个数,表示每个询问的答案。

Sample Input

5 5
2 1 0 2 1
3 3
2 3
2 4
1 2
3 5

Sample Output

1
2
3
0
3

HINT

数据规模和约定
对于100%的数据:
1<=n,m<=200000
0<=ai<=109
1<=l<=r<=n

对于30%的数据:

1<=n,m<=1000

 

离线瞎XX乱搞,只需要先处理出前缀的sg,表示最小没出现的自然数,然后就是

根据影响范围搞线段树即可

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<cstring>
  6 
  7 #define inf 0x7fffffff
  8 using namespace std;
  9 inline int read()
 10 {
 11     int x=0;char ch=getchar();
 12     while(ch<'0'||ch>'9'){ch=getchar();}
 13     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 14     return x;
 15 }
 16 
 17 int n,m,cnt,k=0;
 18 int a[200005],b[200005],sg[200005],ans[200005],next[200005],last[200005];
 19 int ls[600005],rs[600005],mn[600005];
 20 bool mark[200005];
 21 
 22 struct data{int l,r,id;}q[200005];
 23 bool cmp(data a,data b)
 24 {return a.l<b.l;}
 25 int find(int x)
 26 {
 27     int l=1,r=cnt;
 28     while(l<=r)
 29     {
 30         int mid=(l+r)>>1;
 31         if(b[mid]<x)l=mid+1;
 32         else r=mid-1;
 33     }
 34     return l;
 35 }
 36 void build(int k,int l,int r)
 37 {
 38      ls[k]=l;rs[k]=r;mn[k]=inf;
 39      if(l==r){mn[k]=sg[l];return;}
 40      int mid=(l+r)>>1;
 41      build(k<<1,l,mid);build(k<<1|1,mid+1,r);
 42 }
 43 void pushdown(int k)
 44 {
 45      int l=ls[k],r=rs[k];
 46      if(l==r)return;
 47      mn[k<<1]=min(mn[k],mn[k<<1]);
 48      mn[k<<1|1]=min(mn[k],mn[k<<1|1]);
 49 }
 50 int ask(int k,int x)
 51 {
 52     if(mn[k]!=inf)pushdown(k);
 53     int l=ls[k],r=rs[k];
 54     if(l==r)return mn[k];
 55     int mid=(l+r)>>1;
 56     if(x<=mid)return ask(k<<1,x);
 57     return ask(k<<1|1,x);
 58 }
 59 void update(int k,int x,int y,int val)
 60 {
 61      if(mn[k]!=inf)pushdown(k);
 62      int l=ls[k],r=rs[k];
 63      if(l==x&&y==r){mn[k]=min(mn[k],val);return;}
 64      int mid=(l+r)>>1;
 65      if(y<=mid)update(k<<1,x,y,val);
 66      else if(x>mid)update(k<<1|1,x,y,val);
 67      else {update(k<<1,x,mid,val);update(k<<1|1,mid+1,y,val);}
 68 }
 69 int main()
 70 {
 71     n=read(),m=read();
 72     for(int i=1;i<=n;i++)
 73         a[i]=b[i]=read();
 74     sort(b+1,b+n+1);
 75     for(int i=1;i<=n;i++)
 76         if(b[i]!=b[i-1]||i==1)b[++cnt]=b[i];
 77     for(int i=1;i<=n;i++)
 78     {
 79         int t=find(a[i]);
 80         mark[t]=1;
 81         if(a[i]==k)
 82             while(mark[t])
 83                 {
 84                     k++;
 85                     if(b[++t]!=k)break;
 86                 }
 87         sg[i]=k;
 88     }
 89     build(1,1,n);
 90     for(int i=n;i>0;i--)
 91         next[i]=last[find(a[i])],last[find(a[i])]=i;
 92     /*for (int i=1;i<=n;i++)
 93         cout<<next[i]<<" ";
 94     cout<<endl;
 95     for (int i=1;i<=n;i++)
 96         cout<<last[i]<<" ";
 97     cout<<endl;*/
 98     for(int i=1;i<=m;i++)
 99     {
100         q[i].l=read();q[i].r=read();
101         q[i].id=i;
102     }
103     sort(q+1,q+m+1,cmp);
104     int now=1;
105     for(int i=1;i<=m;i++)
106     {
107         while(now<q[i].l)
108         {
109             if(!next[now])next[now]=n+1;
110             update(1,now,next[now]-1,a[now]);
111             now++;
112         }
113         ans[q[i].id]=ask(1,q[i].r);
114     }
115     for(int i=1;i<=m;i++)
116         printf("%d\n",ans[i]);
117 }

 

posted @ 2018-01-15 10:26  Kaiser-  阅读(255)  评论(0编辑  收藏  举报