118kjcom开奖现场  第二作为n个数,  第二行

作者:118kjcom开奖现场

Time Limit:20 SecMemory Limit:128 MB
Submit:1413Solved:713
[Submit][Status][Discuss]

BZOJ3585: mex,bzoj3585mex

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1413  Solved: 713
[Submit][Status][Discuss]

Description

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

Description

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

Input

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

Input

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

Output

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

Output

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

Sample Input

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

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

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

HINT

 

数据规模和约定

  对于100%的数据:

  1<=n,m<=200000

  0<=ai<=109

  1<=l<=r<=n

  对于30%的数据:

  1<=n,m<=1000

 

Source

By 佚名提供

考场上写的cc_hash_table+莫队,成功水到70分233

正解是权值线段树

让线段树中下标为$i$的位置表示权值为$i$的数最后一次出现的位置

同时维护一下区间最小值

再可持久化一下

询问的时候直接在第$r$棵树中找到一个最小的位置,满足这个下标出现的位置$<=l$

#include<cstdio>#include<algorithm>#define getchar() (p1==p2&&(p2=+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)char buf[1<<20],*p1=buf,*p2=buf;using namespace std;const int MAXN=4*1e6+10,INF=1e9+10;inline int read(){    char c=getchar();int x=0,f=1;    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}    return x*f;}struct node{    int mn,ls,rs;}T[MAXN];int root[MAXN],tot=0;void update(int k){T[k].mn=min(T[T[k].ls].mn,T[T[k].rs].mn);}void Insert(int &k,int pre,int l,int r,int pos,int val){    if k=++tot;    if{T[k].mn=val;return ;}    int mid=l+r>>1;    if(pos<=mid) T[k].rs=T[pre].rs,Insert(T[k].ls,T[pre].ls,l,mid,pos,val);    else         T[k].ls=T[pre].ls,Insert(T[k].rs,T[pre].rs,mid+1,r,pos,val);    update;}int Query(int k,int l,int r,int val){    if return l;    int mid=l+r>>1;    if(T[T[k].ls].mn<val) return Query(T[k].ls,l,mid,val);    else                      return Query(T[k].rs,mid+1,r,val);}int main(){    freopen("a.in","r",stdin);    int N=read(),M=read();    for(int i=1;i<=N;i++)    {        int val=read();        Insert(root[i],root[i-1],0,N,val>N?N:val,i);    }    for(int i=1;i<=M;i++)    {        int l=read(),r=read();        printf("%dn",Query(root[r],0,N,l));    }    return 0;}

Source

By 佚名提供

 

 

考场上写的cc_hash_table+莫队,成功水到70分233

正解是权值线段树

让线段树中下标为$i$的位置表示权值为$i$的数最后一次出现的位置

同时维护一下区间最小值

再可持久化一下

询问的时候直接在第$r$棵树中找到一个最小的位置,满足这个下标出现的位置$<=l$

#include<cstdio>
#include<algorithm>
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
char buf[1<<20],*p1=buf,*p2=buf;
using namespace std;
const int MAXN=4*1e6+10,INF=1e9+10;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
struct node
{
    int mn,ls,rs;
}T[MAXN];
int root[MAXN],tot=0;
void update(int k){T[k].mn=min(T[T[k].ls].mn,T[T[k].rs].mn);}
void Insert(int &k,int pre,int l,int r,int pos,int val)
{
    if(!k) k=++tot;
    if(l==r){T[k].mn=val;return ;}
    int mid=l+r>>1;
    if(pos<=mid) T[k].rs=T[pre].rs,Insert(T[k].ls,T[pre].ls,l,mid,pos,val);
    else         T[k].ls=T[pre].ls,Insert(T[k].rs,T[pre].rs,mid+1,r,pos,val);
    update(k);
}
int Query(int k,int l,int r,int val)
{
    if(l==r) return l;
    int mid=l+r>>1;
    if(T[T[k].ls].mn<val) return Query(T[k].ls,l,mid,val);
    else                      return Query(T[k].rs,mid+1,r,val);
}
int main()
{
    freopen("a.in","r",stdin);
    int N=read(),M=read();
    for(int i=1;i<=N;i++)
    {
        int val=read();
        Insert(root[i],root[i-1],0,N,val>N?N:val,i);
    }
    for(int i=1;i<=M;i++)
    {
        int l=read(),r=read();
        printf("%dn",Query(root[r],0,N,l));
    }
    return 0;
}

 

: mex,bzoj3585mex Time Limit:20 Sec Memory Limit:128 MB Submit:1413 Solved:713 [Submit][Status][Discuss] Description 有一个长度为n的数组{a1,a2,...,an}。m次询问...

本文由118kjcom最快开奖现场发布,转载请注明来源

关键词: