• [bzoj3339]Rmq Problem


    【题目描述】

     

    【输入格式】

     

    【输出格式】

     

    【样例输入】

    7 5

    0 2 1 0 1 3 2

    1 3

    2 3

    1 4

    3 6

    2 7

    【样例输出】

    3

    0

    3

    2

    4

    【样例解释与数据范围】

     

    什么都别说,先把暴力30分打出来

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 using namespace std;
     5 
     6 int n,q;
     7 int A[200001];
     8 bool F[200001];
     9 
    10 int main()
    11 {
    12     scanf("%d %d",&n,&q);
    13     for(int i=1;i<=n;i++)
    14         scanf("%d",&A[i]);
    15     for(int i=1;i<=q;i++)
    16     {
    17         int l,r;
    18         memset(F,0,sizeof(F));
    19         cin>>l>>r;
    20         for(int j=l;j<=r;j++)
    21             F[A[j]]=1;
    22         for(int j=0;j<=200000;j++)
    23             if(!F[j])
    24             {
    25                 cout<<j<<endl;
    26                 break;
    27             }
    28     }
    29     return 0;
    30 }

     线段树:

    用mn[i]表示1~i的最小mex值

    每当now<q[i].l时,更新now~next[now]-1节点的最小mex值

    ask查询函数查到最右端的值即为left~right的最小mex值

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 using namespace std;
      5 
      6 const int INF=0x7fffffff;
      7 const int MAXN=200001;
      8 
      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 struct Tree
     18 {
     19     int l,r,id;
     20 }q[MAXN];
     21 
     22 int n,m,k=0;
     23 int a[MAXN],sg[MAXN],next[MAXN],last[MAXN],ans[MAXN];
     24 int ls[MAXN*3],rs[MAXN*3],mn[MAXN*3];
     25 bool mark[MAXN];
     26 
     27 bool cmp(Tree a,Tree b)
     28 {
     29     return a.l<b.l;
     30 }
     31 
     32 void build(int node,int left,int right)//建立区间二叉树
     33 {
     34     ls[node]=left;rs[node]=right;mn[node]=INF;
     35     if(left==right){mn[node]=sg[left];return;}
     36     int mid=(left+right)>>1;
     37     build(node<<1,left,mid);
     38     build(node<<1|1,mid+1,right);
     39 }
     40 
     41 void pushdown(int k)//更新节点mex最小值
     42 {
     43     int l=ls[k],r=rs[k];
     44     if(l==r)return;
     45     mn[k<<1]=min(mn[k],mn[k<<1]);
     46     mn[k<<1|1]=min(mn[k],mn[k<<1|1]);
     47 }
     48 
     49 int ask(int k,int x)//查询mex
     50 {
     51     if(mn[k]!=INF)pushdown(k);
     52     int l=ls[k],r=rs[k];
     53     if(l==r)return mn[k];
     54     int mid=(l+r)>>1;
     55     if(x<=mid) return ask(k<<1,x);
     56     return ask(k<<1|1,x);
     57 }
     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
     68     {
     69         update(k<<1,x,mid,val);
     70         update(k<<1|1,mid+1,y,val);
     71     }
     72 }
     73 
     74 int main()
     75 {
     76     //freopen("mex.txt","w",stdout);
     77     n=read();m=read();
     78     for(int i=1;i<=n;i++)
     79     {
     80         a[i]=read();
     81         mark[a[i]]=1;
     82         if(a[i]==k)
     83             while(mark[k])k++;
     84         sg[i]=k;
     85     }
     86     build(1,1,n);
     87     for(int i=n;i>0;i--)
     88         next[i]=last[a[i]],last[a[i]]=i;//记录上一个a[i]出现的位置
     89     for(int i=1;i<=m;i++)
     90     {
     91         q[i].id=i;
     92         q[i].l=read();
     93         q[i].r=read();
     94     }
     95     sort(q+1,q+m+1,cmp);
     96     int now=1;
     97     for(int i=1;i<=m;i++)
     98     {
     99         while(now<q[i].l)
    100         {
    101             if(!next[now])next[now]=n+1;
    102             update(1,now,next[now]-1,a[now]);
    103             now++;
    104         }
    105         ans[q[i].id]=ask(1,q[i].r);
    106     }
    107     for(int i=1;i<=m;i++)
    108         printf("%d
    ",ans[i]);
    109     return 0;
    110 }

    借鉴了一下黄学长的代码。。。第一次玩线段树(明明是第二次

  • 相关阅读:
    2014.3.3 图像旋转方法
    2014.2.23 datagridview显示图片的方法
    2016.10.8 文件读取和两种模式写入
    2016.8.11 DataTable合并及排除重复方法
    2016.8.17服务器端数据库用户导入导出方法 expdp和impdp
    2016.8.11 禁用360进程防护功能
    2016.7.27 VS搜索正则表达式,在UltraEdit中可选用Perl正则引擎,按C#语法搜索
    2016.6.18主窗体、子窗体InitializeComponent()事件、Load事件发生顺序以及SeleChanged事件的发生
    delphi之猥琐的webserver实现
    HTTP协议中GET、POST和HEAD的介绍
  • 原文地址:https://www.cnblogs.com/InWILL/p/5999556.html
Copyright © 2020-2023  润新知