专栏文章
题解:P12359 [eJOI 2024] 古迹漫步 / Old Orhei
P12359题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minsepuf
- 此快照首次捕获于
- 2025/12/02 07:35 3 个月前
- 此快照最后确认于
- 2025/12/02 07:35 3 个月前
直接暴力查询复杂度是 ,考虑优化。
发现点的数量很少,并且序列 中对多个连续段操作可以合并成一次操作。考虑用线段树进行优化。我们用线段树节点维护序列 中的一个区间 ,表示从某个点出发,经过 序列中的这段区间可以到达哪个点。如果第 个点经过 操作后可以到达 ,经过 操作后可以到达 ,则 可以经过 操作直接到达 ,将节点信息向上更新即可。
CPPstruct Road {
int u, v; // A_u \sim A_v
} rd[N];
struct Tree {
int l, r;
int to[105];
} tree[N << 2];
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
void PushUp(int p) {
for (int i = 1; i <= n; i++) {
tree[p].to[i] = tree[rs(p)].to[tree[ls(p)].to[i]];
}
}
void Build(int p, int l, int r) {
tree[p].l = l;
tree[p].r = r;
if (tree[p].l == tree[p].r) {
for (int i = 1; i <= n; i++) tree[p].to[i] = i;
tree[p].to[rd[a[l]].u] = rd[a[l]].v;
} else {
int mid = (tree[p].l + tree[p].r) >> 1;
Build(ls(p), l + 0, mid);
Build(rs(p), mid + 1, r);
PushUp(p);
}
}
void Change(int p, int x, int d) {
if (tree[p].l == tree[p].r) {
for (int i = 1; i <= n; i++) tree[p].to[i] = i;
tree[p].to[rd[d].u] = rd[d].v;
} else {
int mid = (tree[p].l + tree[p].r) >> 1;
if (x <= mid)Change(ls(p), x, d);
if (mid < x) Change(rs(p), x, d);
PushUp(p);
}
}
int Ask(int p, int l, int r, int s) {
if (l <= tree[p].l && tree[p].r <= r) {
return tree[p].to[s];
} else {
int res = s;
int mid = (tree[p].l + tree[p].r) >> 1;
if (l <= mid) res = Ask(ls(p), l, r, res);
if (mid < r) res = Ask(rs(p), l, r, res);
return res;
}
}
/*====================*/
void Solve() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
rd[i].u = u;
rd[i].v = v;
}
cin >> t;
for (int i = 1; i <= t; i++) {
cin >> a[i];
}
Build(1, 1, t);
cin >> q;
while (q--) {
int op, l, r;
cin >> op >> l >> r;
if (op == 1) {
int s; cin >> s;
cout << Ask(1, l, r, s) << endl;
} else {
Change(1, l, r);
}
}
return;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...