可持久化数据结构
1.trie的可持久化
2.线段树的可持久化——主席树
前提:本身的拓扑结构不变。(例如线段树的分块模型,左右块是不变化的,知识信息在变化)
解决什么样的问题:可以存下数据结构的所有历史版本。
核心思想:只记录每一个版本和前面一个版本的不同之处。
每一次修改不一样的节点,只会记录O(logn)个节点,将平方级别优化成了log级别。
最大异或和
可持久化trie
建立一个新的版本
儿子的信息是不一样的,直接裂开。
不一样的就建立一条新的边。一样的就直接往原来的图上面连接。
#include <bits/stdc++.h>
using namespace std;
const int N = 600002, M = N * 25;
int n, m, sum[N], rt[N], mxid[M], tr[M][2], idx = 0;
void insert(int x, int u, int v)
{
mxid[u] = x;
for (int k = 23; k >= 0; -- k)
{
int y = (sum[x] >> k) & 1;
if(v) tr[u][y ^ 1] = tr[v][y ^ 1];
tr[u][y] = ++ idx;
u = tr[u][y], v = tr[v][y], mxid[u] = x;
}
return ;
}
int query(int u, int x, int L)
{
int tot = 0;
for (int k = 23; k >= 0; -- k)
{
int y = (x >> k) & 1;
if(mxid[tr[u][y ^ 1]] >= L) u = tr[u][y ^ 1], tot += (1 << k);
else u = tr[u][y];
}
return x ^ sum[mxid[u]];
}
int main()
{
scanf("%d %d", &n, &m);
mxid[0] = -1, rt[0] = ++ idx;
insert(0, rt[0], 0);
for (int i = 1; i <= n; ++ i)
{
int x;
scanf("%d", &x);
sum[i] = sum[i - 1] ^ x, rt[i] = ++ idx;
insert(i, rt[i], rt[i - 1]);
}
for (int i = 1; i <= m; ++ i)
{
char s[2]; int x, l, r;
scanf("%s", s);
if(*s == 'A')
{
scanf("%d", &x);
n ++, sum[n] = sum[n - 1] ^ x, rt[n] = ++ idx;
insert(n, rt[n], rt[n - 1]);
}
else
{
scanf("%d %d %d", &l, &r, &x);
printf("%d\n", query(rt[r - 1], sum[n] ^ x, l - 1));
}
}
return 0;
}
第K小数
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
struct segement_tree
{
int l, r, cnt;
}tr[N * 21];
int idx = 0, rt[N], n, m, a[N], b[N], tot;
void push_up(int p) {tr[p].cnt = tr[tr[p].l].cnt + tr[tr[p].r].cnt; }
int build_tree(int l, int r)
{
int p = ++ idx;
if(l == r) return p;
int mid = l + r >> 1;
tr[p].l = build_tree(l, mid), tr[p].r = build_tree(mid + 1, r);
return p;
}
int insert(int p, int l, int r, int x)
{
int q = ++ idx;
tr[q] = tr[p];
if(l == r) {tr[q].cnt ++; return q; }
int mid = l + r >> 1;
if(x <= mid) tr[q].l = insert(tr[p].l, l, mid, x);
else tr[q].r = insert(tr[p].r, mid + 1, r, x);
push_up(q);
return q;
}
int query(int q, int p, int l, int r, int k)
{
if(l == r) return l;
int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
int mid = l + r >> 1;
if(k <= cnt) return query(tr[q].l, tr[p].l, l, mid, k);
else return query(tr[q].r, tr[p].r, mid + 1, r, k - cnt);
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]), b[i] = a[i];
sort(b + 1, b + n + 1);
tot = unique(b + 1, b + n +1) - b - 1;
for (int i = 1; i <= n; ++ i) a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b;
rt[0] = build_tree(1, tot);
for (int i = 1; i <= n; ++ i)
{
rt[i] = insert(rt[i - 1], 1, tot, a[i]);
}
for (int i = 1; i <= m; ++ i)
{
int l, r, k;
scanf("%d %d %d", &l, &r, &k);
printf("%d\n", b[query(rt[r], rt[l - 1], 1, tot, k)]);
}
return 0;
}

浙公网安备 33010602011771号