学会动态开点很重要。
本代码采用指针形式,点区间为左闭右开。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
inline ll read()
{
ll x = 0, f = 0;
char ch = getchar();
while (!isdigit(ch))
f |= (ch == '-'), ch = getchar();
while (isdigit(ch))
x = (x << 1) + (x << 3) + (ch ^= 48), ch = getchar();
return f ? -x : x;
}
const ll N = 1e6 + 3;
int n, m, tot, a[N];
struct node
{
int L, R, w;
node *lc, *rc;
};
struct node by[N * 21], *pool = by, *root[N];
node *New()
{
return ++pool;
}
node *build(int l, int r)
{
node *now = New();
now->L = l;
now->R = r;
if (l + 1 < r)
{
ll mid = (now->L + now->R) >> 1;
now->lc = build(l, mid);
now->rc = build(mid, r);
}
else
{
now->w = a[l];
now->lc = now->rc = NULL;
}
return now;
}
inline bool out(node *&now, int l, int r)
{
return (now->R <= l) || (r < now->L);
}
void change(node *&pre, node *&now, int x, int w)
{
*now = *pre;
if (pre->L == x and pre->R == x + 1)
now->w = w;
else
{
if (!out(pre->lc, x, x + 1))
{
now->lc = New();
change(pre->lc, now->lc, x, w);
}
else
{
now->rc = New();
change(pre->rc, now->rc, x, w);
}
}
}
int check(node *now, int x)
{
if (now->L == x && now->R == x + 1)
return now->w;
if (!out(now->lc, x, x + 1))
return check(now->lc, x);
else
return check(now->rc, x);
}
int main()
{
n = read(), m = read();
for (int i = 1; i <= n; ++i)
{
a[i] = read();
}
root[0] = build(1, n + 1);
for (int i = 0; i < m; ++i)
{
ll v = read(), opt = read(), x = read(), k;
if (opt == 1)
{
k = read();
root[++tot] = New();
change(root[v], root[tot], x, k);
}
else
{
ll ans = check(root[v], x);
printf("%lld\n", ans);
root[++tot] = New();
root[tot] = root[v];
}
}
return 0;
}