JZOJ-senior-3547. 【清华集训2014】mex

版权声明:本文为博主原创文章,未经博主允许不得转载。 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));
	}
}

猜你喜欢

转载自blog.csdn.net/HuangXinyue1017/article/details/83504281
今日推荐