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

xiaoxiao2025-04-13  11

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)); } }
转载请注明原文地址: https://www.6miu.com/read-5028172.html

最新回复(0)