版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HuangXinyue1017/article/details/83504281
Time Limits: 2000 ms Memory Limits: 131072 KB
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
Data Constraint
对于30%的数据:
1<=n,m<=1000
对于100%的数据:
1<=n,m<=200000
0<=ai<=10^9
1<=l<=r<=n
Solution
- 主席树,记录每个值最晚出现的位置
Code
#include<algorithm>
#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int N=2e5+5,MX=1e9;
int n,m,u,v,tot,rt[N];
struct tree{int l,r,mn;}tr[30*N+N];
void ins(int x,int &y,int l,int r,int id)
{
y=++tot,tr[y]=tr[x];
if(l==r) {tr[y].mn=id; return;};
int mid=(l+r)>>1;
if(u<=mid) ins(tr[x].l,tr[y].l,l,mid,id);
else ins(tr[x].r,tr[y].r,mid+1,r,id);
tr[y].mn=min(tr[tr[y].l].mn,tr[tr[y].r].mn);
}
int ask(int x,int l,int r)
{
if(l==r) return l;
int mid=(l+r)>>1;
if(tr[tr[x].l].mn<u) return ask(tr[x].l,l,mid);
else return ask(tr[x].r,mid+1,r);
}
int main()
{
scanf("%d%d",&n,&m);
fo(i,1,n)
{
scanf("%d",&u);
ins(rt[i-1],rt[i],0,MX,i);
}
fo(i,1,m)
{
scanf("%d%d",&u,&v);
printf("%d\n",ask(rt[v],0,MX));
}
}