CF1725K
发现每次操作 3 至多会增加两种数值,故总的数值不会超过
使用并查集模拟合并即可,实现时用 set 维护现有的数的集合,每次二分出要修改的数,时空复杂度
Code:
#include <bits/stdc++.h>
typedef long long ll;
typedef double db;
#define ull unsigned long long
#define ldb long double
#define pii pair<int, int>
#define mkp make_pair
#define pb push_back
#define pc putchar
#define sp pc(' ')
#define et puts("")
#define debug cerr<<"--ERROR--"<<endl
#define rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define per(i, a, b) for(int i = (a); i >= (b); --i)
#define mem(a, x) memset(a, x, sizeof(a))
#define in(a, n) rep(i, 1, n) a[i]=rd()
#define all(x) x.begin(), x.end()
using namespace std;
inline ll rd(){ll x=0, f=1; char c=getchar(); while(c<'0' || c>'9') {if(c=='-') f=-1; c=getchar();} while(c>='0' && c<='9') {x=x*10+c-48; c=getchar();} return x*f;}
inline void wr(ll x){if(x<0) putchar('-'), x=-x; if(x>9) wr(x/10); putchar(x%10+48);}
const ldb eps = 1e-9;
const ll INF = 0x3f3f3f3f;
const int mo = 1e9+7;
const int N = 1.6e6+3;
int n, q, f[N], val[N], tot;
map <int, int> pos;
set <int> s;
void clear() { }
int find(int k) {
return f[k]==k ? k : f[k]=find(f[k]);
}
int newnode(int x) {
s.insert(x);
val[++tot]=x, f[tot]=tot;
return tot;
}
void modify(int i, int x) {
if(!pos[x]) pos[x] = newnode(x);
f[i] = pos[x];
}
signed main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
int TT = 1;
//TT = rd();
while(TT--)
{
cin >> n;
rep(i, 1, n) f[i]=i;
tot=n;
rep(i, 1, n) {
int x=rd();
modify(i, x);
}
s.insert(INF);
cin >> q;
while(q--) {
int op, k, v, l, r;
op=rd();
if(op == 1) {
k=rd(), v=rd();
modify(k, v);
}
if(op == 2) {
k=rd();
wr(val[find(k)]), et;
}
if(op == 3) {
l=rd(), r=rd();
for(auto it = s.lower_bound(l); (v=*it) <= r; it = s.lower_bound(l)) {
modify(pos[v], v-l < r-v ? l-1 : r+1);
pos[v]=0, s.erase(it);
}
}
}
et;
if(TT) clear();
}
return 0;
}
/*
*/
并查集数组记得要开两倍。