题目链接:点击查看
题目大意:给出一个1~n的序列,然后给出m个操作,每个操作分为下列两种情况:
- 1 x:让数字x不可用
- 2 x:查询包括x在内的右侧的第一个可用数字
题目分析:因为n给到了1e9,而查询只有1e6,所以我们必须将数据离散化,我最初的思路是先将1e6个查询记录下来,将操作1使用过的数字放到一个有序数列中,离线处理,可以倒着一步步模拟,每次遇到操作1就将其删除(即加入回原数组中),然后二分查找第一个大于等于它本身的数,我让队友模拟的,最后果然这个题目卡了stl的时间,TLE了,然后我就想用vector模拟链表写一下这个题,经过队友的提醒,发现了这就是一个离散化后的并查集,但我不太会写,就先用vector正向模拟的这个题目,最后还是以TLE告终,临比赛结束前半个小时终于有了最终的思路,就是在离散化的时候,将涉及到的x和x+1同时加入到并查集中,这样正向遍历一遍询问,每次遇到删除就将当前节点的父节点改为下个节点的父节点,遇到询问就直接输出该节点的父节点即可
不过还是需要注意一下离散化后的id和并查集的对应关系,写那一部分的时候一定要细心想一下,不能对应错
还有个细节需要注意一下,因为每次push进去的是点x和点x+1,所以最坏情况会有2e6个点,所以数组要开2e6,开1e6会RE
题解是说用map并查集维护一条链表,不过不能用普通的map,会超时,要用unordered_map,据说是O1的查询
补充一下map和unordered_map的区别吧:
map:
map内部实现了一个红黑树,该结构具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素,因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行这样的操作,故红黑树的效率决定了map的效率。
unordered_map:unordered_map内部实现了一个哈希表,因此其元素的排列顺序是杂乱的,无序的
其他方法都是一样的用法
蒟蒻的代码:(又臭又长但条理还挺清晰的-.-)
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=2e6+100;
vector<int>v;
int fa[N];
int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}
struct Node
{
int op,x;
}q[N];
int getid(int x)
{
return lower_bound(v.begin(),v.end(),x)-v.begin();
}
int main()
{
// freopen("input.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
v.clear();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].op,&q[i].x);
v.push_back(q[i].x);
v.push_back(q[i].x+1);
}
v.push_back(n);
sort(v.begin(),v.end());//离散化+去重
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=0;i<v.size();i++)
fa[i]=i;
for(int i=1;i<=m;i++)
{
int op=q[i].op;
int x=q[i].x;
int id=getid(x);
if(op==1)
{
fa[id]=find(id+1);
}
else
{
printf("%d\n",v[find(id)]);
}
}
}
return 0;
}
题解的代码:顺便偷学了一波unordered_map
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
unordered_map<int, int> fa;
int findfa(int x) {
if (!fa.count(x)) return x;
return fa[x] = findfa(fa[x]);
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
int n, q;
scanf("%d %d", &n, &q);
int op, x;
while (q--) {
scanf("%d %d", &op, &x);
if (op == 1) {
fa[x] = findfa(x + 1);
} else {
int ans = findfa(x);
if (ans > n) ans = -1;
printf("%d\n", ans);
}
}
return 0;
}