Description
There are n points in an array with index from 1 to n, and there are two operations to those points.
1: 1 x marking the point x is not available
2: 2 x query for the index of the first available point after that point (including x itself) .
Input
n q
z1 x1
.
.
.
zq xq
q is the number of queries, z is the type of operations, and x is the index of operations. 1≤x<n<109, 1≤q<106 and z is 1 or 2
Output
Output the answer for each query.
Sample Input
5 3
1 2
2 2
2 1
Sample Output
3
1
题目大意:
有n个点,标号从1~n。有q个操作,操作有两种:
1:1 x 使点x失效。
2:2 x 问从x开始,第一个有效点是哪个。
核心思想:
先将数据离散化。
每个点的初始祖先都是自己。在点x失效之前将点x的祖先更新为点x+1的祖先,也就是f[x]=find(x+1)。
此题充分体现出了并查集find函数在寻祖先时压缩路径的优点。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+20;
//en是离散后数组的大小,b数组用来离散化,f数组存祖先
int en,b[N<<1],f[N<<1];
//存操作
struct Node{
int z,x;
}h[N];
//并查集寻祖先
int find(int x)
{
if(f[x]==x)
return x;
return f[x]=find(f[x]);
}
//离散映射
int getid(int x)
{
return lower_bound(b,b+en,x)-b+1;
}
int main()
{
int n,q,ct=0;
//输入
scanf("%d%d",&n,&q);
for(int i=0;i<q;i++)
{
scanf("%d%d",&h[i].z,&h[i].x);
b[ct++]=h[i].x;
b[ct++]=h[i].x+1;
}
//离散
sort(b,b+ct);
en=unique(b,b+ct)-b;
//并查集初始化
for(int i=0;i<=en;i++)
f[i]=i;
//q次操作
for(int i=0;i<q;i++)
{
int t=getid(h[i].x);
if(h[i].z==1)
f[t]=find(t+1);
else
printf("%d\n",b[find(t)-1]);
}
return 0;
}