#include <iostream>
#include <cstdio>
#include <map>
#include <set>
#include <iterator>
#include <cctype>
#define int long long
using namespace std;
int cntForDebug = 0;
inline void qwq() {
cout << "QwQ " << ++ cntForDebug << " Times!\n";
}
set <int> se;
map <int, int> mp;
const int N = 2e5 + 10, INF = -1e9;
struct arrQue {
int opt, x, y;
} q[N];
int get_integer() {
char ch;
int opt = 1, x;
while (!isdigit(ch = getchar()))
if (ch == '-')
opt = -1;
x = ch ^ '0';
while (isdigit(ch = getchar()))
x = (x << 3) + (x << 1) + (ch ^ '0');
return x * opt;
}
long long get_llinteger() {
char ch;
int opt = 1;
long long x;
while (!isdigit(ch = getchar()))
if (ch == '-')
opt = -1;
x = ch ^ '0';
while (isdigit(ch = getchar()))
x = (x << 3LL) + (x << 1LL) + (ch ^ '0');
return x * opt;
}
inline void swap(int &x, int &y) {
int t = x;
x = y;
y = t;
}
int tot, n, t, lca;
struct Node {
int l, r;
int mx, pre, suf;
} z[N << 2];
void dg(int l, int r, int rt, int nowl, int nowr) {
if (nowl <= l && r <= nowr) {
if (t > z[rt].mx)
return ;
t = z[rt].mx;
if (l == r) {
lca = l;
return ;
}
int mid = l + r >> 1;
dg(l, mid, rt << 1, nowl, nowr);
dg(mid + 1, r, rt << 1 | 1, nowl, nowr);
return ;
}
int mid = l + r >> 1;
if (nowl <= mid)
dg(l, mid, rt << 1, nowl, nowr);
if (mid < nowr)
dg(mid + 1, r, rt << 1 | 1, nowl, nowr);
}
int get_lca(int u, int v) {
t = 0, lca = 0;
if (u > v)
swap (u, v);
dg(1, tot, 1, u, v);
return lca;
}
int calc_pre(int l, int r, int rt, int x) {
if (l == r) {
if (x < z[rt].mx)
return 1;
return 0;
}
int mid = l + r >> 1;
if (x < z[rt << 1].mx)
return calc_pre(l, mid, rt << 1, x) + z[rt].pre;
return calc_pre(mid + 1, r, rt << 1 | 1, x);
}
int calc_suf(int l, int r, int rt, int x) {
if (l == r) {
if (x < z[rt].mx)
return 1;
return 0;
}
int mid = l + r >> 1;
if (x < z[rt << 1 | 1].mx)
return calc_suf(mid + 1, r, rt << 1 | 1, x) + z[rt].suf;
return calc_suf(l, mid, rt << 1, x);
}
void update(int l, int r, int rt) {
int mid = l + r >> 1;
z[rt].mx = max(z[rt << 1].mx, z[rt << 1 | 1].mx);
z[rt].pre = calc_pre(mid + 1, r, rt << 1 | 1, z[rt << 1].mx);
z[rt].suf = calc_suf(l, mid, rt << 1, z[rt << 1 | 1].mx);
}
void modify(int l, int r, int rt, int p, int v) {
if (l == r) {
z[rt].mx = v;
return ;
}
int mid = l + r >> 1;
if (p <= mid)
modify(l, mid, rt << 1, p, v);
else
modify(mid + 1, r, rt << 1 | 1, p, v);
update(l, r, rt);
}
int query_pre(int l, int r, int rt, int x) {
if (x <= l) {
int res = calc_pre(l, r, rt, t);
t = max(t, z[rt].mx);
return res;
}
int mid = l + r >> 1;
int res = 0;
if (x <= mid)
res += query_pre(l, mid, rt << 1, x);
res += query_pre(mid + 1, r, rt << 1 | 1, x);
return res;
}
int query_suf(int l, int r, int rt, int x) {
if (x >= r) {
int res = calc_suf(l, r, rt, t);
t = max(t, z[rt].mx);
return res;
}
int mid = l + r >> 1;
int res = 0;
if (x > mid)
res += query_suf(mid + 1, r, rt << 1 | 1, x);
res += query_suf(l, mid, rt << 1, x);
return res;
}
int query(int x) {
int ans = 0;
t = 0;
ans += query_pre(1, tot, 1, x);
t = 0;
ans += query_suf(1, tot, 1, x);
return ans - 1;
}
inline void insert(int k, int w) {
modify(1, tot, 1, mp[k], w);
}
inline void del(int k) {
modify(1, tot, 1, mp[k], 0);
}
inline int get_dist(int u, int v) {
u = mp[u], v = mp[v];
return query(u) + query(v) - 2 * query(get_lca(u, v));
}
signed main() {
n = get_llinteger();
for (int i = 1; i <= n; i ++) {
q[i].opt = get_llinteger();
if (q[i].opt == 0)
q[i].x = get_llinteger(), q[i].y = get_llinteger();
else if (q[i].opt == 1)
q[i].x = get_llinteger();
else
q[i].x = get_llinteger(), q[i].y = get_llinteger();
}
for (int i = 1; i <= n; i ++)
if (q[i].opt == 0)
se.insert(q[i].x);
for (auto &u : se)
mp[u] = ++ tot;
for (int i = 1; i <= n; i ++) {
int &opt = q[i].opt;
if (opt == 0) {
int k, w;
k = q[i].x, w = q[i].y;
insert(k, w);
}
else if (opt == 1) {
int k;
k = q[i].x;
del(k);
}
else {
int u, v;
u = q[i].x, v = q[i].y;
cout << get_dist(u, v) << '\n';
}
}
return 0;
}
CodeChef COT5 / SPOJ COT5【线段树】【毒瘤】【动态LCA】
最新推荐文章于 2024-09-11 15:28:58 发布