BZOJ 3673 && BZOJ 3674 可持久化线段树

来源:互联网 发布:天津网络推广公司排名 编辑:程序博客网 时间:2024/03/28 20:20

n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
0<n,m21040<n,m2105

其实就是要打一个可持久化数组。
其实就是要打一个可持久化线段树QAQ
其实一直很想学来着QAQ
以前是打过动态开点线段树。
现在想想其实有些相似诶
合并集合的时候好像可以启发式合并诶
是按集合的轶合并的QAQ
大概是这样的啦

void Modify(int &o, int x, int l, int r, int pos, int k) {    o = ++Tcnt;    if (l == r) {        fa[o] = k; Rank[o] = Rank[x];        return;    }    ls[o] = ls[x]; rs[o] = rs[x];    int mid = (l + r) >> 1;    if (pos <= mid) Modify(ls[o], ls[x], l, mid, pos, k);    else Modify(rs[o], rs[x], mid + 1, r, pos, k);}
if (Rank[p1] > Rank[p2]) swap(p1, p2);Modify(rt[i], rt[i - 1], 1, n, fa[p1], fa[p2]);if (Rank[p1] == Rank[p2]) Add(rt[i], 1, n, fa[p2]);

终于算打过可持久化线段树了QAQ

#include <cstdio>#include <cstdlib>#include <iostream>using namespace std;const int N = 10000100;inline char get(void) {    static char buf[1000000], *p1 = buf, *p2 = buf;    if (p1 == p2) {        p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin);        if (p1 == p2) return EOF;    }    return *p1++;}inline void read(int &x) {    x = 0; char c = get(); int sign = 1;    for (; c < '0' || c > '9'; c = get()) if(c == '-') sign = 0;    for (; c >= '0' && c <= '9'; x = (x << 1) + (x << 3) + c - '0', c = get());    x = sign ? x : -x;}int rt[200010], ls[N], rs[N], fa[N], Rank[N];int n, m, x, y, opr, Tcnt, p1, p2, last;void Build(int &o, int l, int r) {    if (!o) o = ++Tcnt;    if (l == r) {        fa[o] = l; return;    }    int mid = (l + r) >> 1;    Build(ls[o], l, mid);    Build(rs[o], mid + 1, r);}int Query(int o, int l, int r, int pos) {    if (l == r) return o;    int mid = (l + r) >> 1;    if (pos <= mid) return Query(ls[o], l, mid, pos);    else return Query(rs[o], mid + 1, r, pos);}void Modify(int &o, int x, int l, int r, int pos, int k) {    o = ++Tcnt;    if (l == r) {        fa[o] = k; Rank[o] = Rank[x];        return;    }    ls[o] = ls[x]; rs[o] = rs[x];    int mid = (l + r) >> 1;    if (pos <= mid) Modify(ls[o], ls[x], l, mid, pos, k);    else Modify(rs[o], rs[x], mid + 1, r, pos, k);}void Add(int o, int l, int r, int pos) {    if (l == r) {        Rank[o]++; return;    }    int mid = (l + r) >> 1;    if (pos <= mid) Add(ls[o], l, mid, pos);    else Add(rs[o], mid + 1, r, pos);}int find(int rt, int x) {    int Pos = Query(rt, 1, n, x);    if (x == fa[Pos]) return Pos;    return find(rt, fa[Pos]);}int main(void) {    freopen("1.in", "r", stdin);    read(n); read(m);    Build(rt[0], 1, n);    for (int i = 1; i <= m; i++) {        read(opr);        if (opr == 1) {            read(x); read(y); rt[i] = rt[i - 1];            x ^= last; y ^= last;            p1 = find(rt[i], x); p2 = find(rt[i], y);            if (fa[p1] == fa[p2]) continue;            if (Rank[p1] > Rank[p2]) swap(p1, p2);            Modify(rt[i], rt[i - 1], 1, n, fa[p1], fa[p2]);            if (Rank[p1] == Rank[p2]) Add(rt[i], 1, n, fa[p2]);        } else if (opr == 2) {            read(x); x ^= last; rt[i] = rt[x];        } else {            read(x); read(y); rt[i] = rt[i - 1];            x ^= last; y ^= last;            p1 = find(rt[i], x); p2 = find(rt[i], y);            if (fa[p1] == fa[p2]) {                puts("1"); last = 1;            } else {                puts("0"); last = 0;            }        }    }    return 0;}
0 0