【主席树】可持久化数组(金牌导航 可持久化数据结构-3)
生活随笔
收集整理的這篇文章主要介紹了
【主席树】可持久化数组(金牌导航 可持久化数据结构-3)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
可持久化數組
金牌導航 可持久化數據結構-3
題目大意
給出一個序列a,讓你執行若干操作,操作分為兩種:
1.繼承第v次操作后把第x個數改成y
2.查詢第v次操作的第x個數的值
輸入樣例
5 10 59 46 14 87 41 0 2 1 0 1 1 14 0 1 1 57 0 1 1 88 4 2 4 0 2 5 0 2 4 4 2 1 2 2 2 1 1 5 91輸出樣例
59 87 41 87 88 46數據范圍
1?N,M?106,1?xi?N,0?vi<i,?109?ai,yi?1091\leqslant N,M\leqslant 10^6,1\leqslant x_i\leqslant N,0\leqslant v_i< i,-10^9\leqslant a_i,y_i\leqslant 10^91?N,M?106,1?xi??N,0?vi?<i,?109?ai?,yi??109
解題思路
如果直接暴力存數組,每次操作copy一遍會TLE/MLE
這里可以用搜索樹的方法,就是把每個操作和所繼承的操作連一條邊,然后搜索即可,時間O(m)O(m)O(m)(這里不做詳解)
對于這樣一個序列,可以用主席樹來維護
對于每次修改就和模板一樣,然后查詢就直接搜目標節點即可
時間O(mlogn)O(mlogn)O(mlogn),不如搜索樹?
代碼
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define ll long long #define N 1000010 using namespace std; int n, m, x, y, v, p, w, g, num, a[N], s[N << 5], ls[N << 5], rs[N << 5], root[N]; int build(int l, int r) {int x = ++w;if (l == r) {s[x] = a[l];return x;}int mid = (l + r) >> 1;ls[x] = build(l, mid);rs[x] = build(mid + 1, r);return x; } int change(int lst, int v, int y, int l, int r) {int x = ++w;if (l == r) {s[x] = y;return x;}int mid = (l + r) >> 1;if (v <= mid)ls[x] = change(ls[lst], v, y, l, mid), rs[x] = rs[lst];elsels[x] = ls[lst], rs[x] = change(rs[lst], v, y, mid + 1, r);return x; } int ask(int v, int x, int l, int r) {if (l == r) {return s[v];}int mid = (l + r) >> 1;if (x <= mid)return ask(ls[v], x, l, mid);elsereturn ask(rs[v], x, mid + 1, r); } int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);root[0] = build(1, n);for (int i = 1; i <= m; ++i) {scanf("%d%d%d", &v, &p, &x);if (p & 1) {scanf("%d", &y);root[i] = change(root[v], x, y, 1, n);//修改} else {root[i] = root[v];//數組沒變,直接copyprintf("%d\n", ask(root[v], x, 1, n));//查詢}}return 0; }總結
以上是生活随笔為你收集整理的【主席树】可持久化数组(金牌导航 可持久化数据结构-3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 事件查看器的使用事件查看器的使用范围
- 下一篇: 怎样在dos下查看路由命令dos开启路由