zoukankan      html  css  js  c++  java
  • [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 }

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

  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/InWILL/p/5999556.html
Copyright © 2011-2022 走看看