BZOJ3674 可持久化并查集加强版
2014-10-04 17:07
387 查看
这是以前做的一道题。
并查集 <=>一个father数组,于是可持久化并查集 <=>可持久化数组。
然后数组如何可持久化呢?用可持久化线段树实现。
每次合并就等价于修改father数组的一个值,就是线段树点修改。
然后查询也是,查father数组中的一个值,就是线段树点查询。
要查询历史版本,就套上可持久化即可。
View Code
(p.s. 作为一名典型的嘴巴选手,还是要Orz hzwer的程序!!!)
并查集 <=>一个father数组,于是可持久化并查集 <=>可持久化数组。
然后数组如何可持久化呢?用可持久化线段树实现。
每次合并就等价于修改father数组的一个值,就是线段树点修改。
然后查询也是,查father数组中的一个值,就是线段树点查询。
要查询历史版本,就套上可持久化即可。
/************************************************************** Problem: 3674 User: rausen Language: C++ Result: Accepted Time:1496 ms Memory:158228 kb ****************************************************************/ #include <cstdlib> #include <cstdio> #include <algorithm> using namespace std; struct segment{ int ls, rs, v, dep; } seg[10000000]; int tot, last, m, n, root[300000]; void build_seg(int &p, int l, int r){ if (!p) p = ++tot; if (l == r){ seg[p].v = l; return; } int m = (l + r) >> 1; build_seg(seg[p].ls, l, m); build_seg(seg[p].rs, m + 1, r); } void modify(int l, int r, int x, int &y, int pos, int val){ y = ++tot; if (l == r){ seg[y].v = val; return; } seg[y].ls = seg[x].ls; seg[y].rs = seg[x].rs; int m = (l + r) >> 1; if (pos <= m) modify(l, m, seg[x].ls, seg[y].ls, pos, val); else modify(m + 1, r, seg[x].rs, seg[y].rs, pos, val); } void add(int p, int l, int r, int pos){ if (l == r){ ++seg[p].dep; return; } int m = (l + r) >> 1; if (pos <= m) add(seg[p].ls, l, m, pos); else add(seg[p].rs, m + 1, r, pos); } int query(int p, int l, int r, int pos){ if (l == r) return p; int m = (l + r) >> 1; if (pos <= m) return query(seg[p].ls, l, m, pos); else return query(seg[p].rs, m + 1, r, pos); } int find(int p, int x){ int k = query(p, 1, n, x); if (x == seg[k].v) return k; int t = find(p, seg[k].v); modify(1, n, p, p, seg[k].v, t); return t; } int main(){ scanf("%d %d\n", &n, &m); build_seg(root[0], 1, n); int oper, x, y, p, q; for(int i = 1; i <= m; ++i){ scanf("%d", &oper); if (oper == 1){ scanf("%d%d", &x, &y); x = x ^ last, y = y ^ last; root[i] = root[i - 1]; p = find(root[i], x), q = find(root[i], y); if (seg[p].v == seg[q].v) continue; if (seg[p].dep > seg[q].dep) swap(p, q); modify(1, n, root[i - 1], root[i], seg[p].v, seg[q].v); if (seg[p].dep == seg[q].dep) add(root[i], 1, n, seg[q].v); } else if (oper == 2){ scanf("%d", &x); x = x ^ last; root[i] = root[x]; } else{ scanf("%d%d", &x ,&y); x = x ^ last, y = y ^ last; root[i] = root[i - 1]; p = find(root[i], x), q = find(root[i], y); if (seg[p].v == seg[q].v) last = 1; else last = 0; printf("%d\n", last); } } return 0; }
View Code
(p.s. 作为一名典型的嘴巴选手,还是要Orz hzwer的程序!!!)
相关文章推荐
- 【BZOJ】【3673】可持久化并查集 & 【3674】可持久化并查集加强版
- bzoj 3674 可持久化并查集加强版
- 【可持久化并查集】BZOJ3674[可持久化并查集加强版]题解
- BZOJ 3673 可持久化并查集 by zky && 3674 可持久化并查集加强版
- 【BZOJ3674】可持久化并查集加强版
- 【BZOJ】3674: 可持久化并查集加强版
- Bzoj 3674: 可持久化并查集加强版
- BZOJ - 3674 - 可持久化并查集加强版
- bzoj 3674: 可持久化并查集加强版
- 【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之
- BZOJ 3674 可持久化并查集加强版(按秩合并版本)
- BZOJ 3674: 可持久化并查集加强版
- [BZOJ3674]可持久化并查集加强版&[BZOJ3673]可持久化并查集 by zky
- BZOJ 3674 可持久化并查集加强版(路径压缩版本)
- [BZOJ 3674]可持久化并查集加强版
- [bzoj3674/3673]可持久化并查集加强版 主席树
- [BZOJ] 3674 可持久化并查集加强版(主席树广泛运用)
- 可持久性数组 bzoj3674 可持久化并查集加强版
- [BZOJ3674]可持久化并查集加强版
- bzoj 3674: 可持久化并查集加强版