• 【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
    ",ans[i]);
    117 }
  • 相关阅读:
    老天待我不薄,又来这么一题POJ1753
    HDOJ4857【拓扑排序】
    二分匹配ZOJ3646
    poj3185//BFS随便切...
    poj2239 poj1274【二分匹配】
    每天一水poj1502【最短路】
    POJ1466/HDOJ1068 谈谈二分匹配的时间复杂度
    纯拓扑排序一搞poj2367
    poj1477(水)
    用动态链表high-poj 1528
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8286964.html
Copyright © 2020-2023  润新知