题目链接:https://nanti.jisuanke.com/t/41384
题意:给你一个n代表你拥有了n个数,有q个操作,op=1 x 是使得x不可被利用,op = 2 x 是查询[x, n]中,第一个可被利用的是谁(n<= 1e9)
当时做题的时候,根本没想到暴力会过,数据太水了,我tm二分加树状数组都超时,他们一个unordered_map暴力过了?
不过正解是并查集+离线处理,可以发现,你删除一个数x,那么x+1一定是当前可被利用的最小的数,所以只需要记录被删除的点和被删除点+1位置的点即可,还有需要加上需要查询的点,因为最终结果可能是他本身
这样对于每个操作,如果是删除,就让当前x和x+1连在一起,否则就输出当前x的父亲节点
#include <cstdio>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;
struct node{
int op, x;
}pos[maxn];
unordered_map<int, int> mp;
int getf(int x){
return x == mp[x] ? x : mp[x] = getf(mp[x]);
}
void merg1e(int x, int y){
int t1 = getf(x);
int t2 = getf(y);
if(t1 != t2) {
mp[t1] = t2;
}
}
int main(){
int n, q;
scanf("%d%d", &n, &q);
for(int i = 0; i < q; i++) {
scanf("%d%d" ,&pos[i].op, &pos[i].x);
if(pos[i].op == 1){
mp[pos[i].x] = pos[i].x;
mp[pos[i].x + 1] = pos[i].x + 1;
}
else mp[pos[i].x] = pos[i].x;
}
for(int i = 0; i < q; i++) {
if(pos[i].op == 1) merg1e(mp[pos[i].x], mp[pos[i].x + 1]);
else printf("%d\n", getf(mp[pos[i].x]));
}
return 0;
}