zoukankan      html  css  js  c++  java
  • [BZOJ3673]可持久化并查集 by zky

    [BZOJ3673]可持久化并查集 by zky

    试题描述

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

    0<n,m<=2*10^4

    输入

    见“试题描述

    输出

    见“试题描述

    输入示例

    5 6
    1 1 2
    3 1 2
    2 0
    3 1 2
    2 1
    3 1 2

    输出示例

    1
    0
    1

    数据规模及约定

    见“试题描述

    题解

    用启发式合并的并查集,用主席树维护可持久化数组。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 20010
    #define maxnode 1266666
    
    int ToT, fa[maxnode], siz[maxnode], lc[maxnode], rc[maxnode];
    void updatefa(int& y, int x, int l, int r, int p, int Fa) {
    	fa[y = ++ToT] = fa[x]; siz[y] = siz[x];
    	if(l == r){ fa[y] = Fa; return ; }
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) updatefa(lc[y], lc[x], l, mid, p, Fa);
    	else updatefa(rc[y], rc[x], mid+1, r, p, Fa);
    	return ;
    }
    void updatesiz(int& y, int x, int l, int r, int p, int Siz) {
    	fa[y = ++ToT] = fa[x]; siz[y] = siz[x];
    	if(l == r){ siz[y] = Siz; return ; }
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) updatesiz(lc[y], lc[x], l, mid, p, Siz);
    	else updatesiz(rc[y], rc[x], mid+1, r, p, Siz);
    }
    int qfa(int o, int l, int r, int p) {
    	if(!o) return 0;
    	if(l == r) return fa[o];
    	int mid = l + r >> 1;
    	if(p <= mid) return qfa(lc[o], l, mid, p);
    	return qfa(rc[o], mid+1, r, p);
    }
    int qsiz(int o, int l, int r, int p) {
    	if(!o) return 0;
    	if(l == r) return siz[o];
    	int mid = l + r >> 1;
    	if(p <= mid) return qsiz(lc[o], l, mid, p);
    	return qsiz(rc[o], mid+1, r, p);
    }
    
    int n, rt[maxn];
    int findset(int o, int x) {
    	int tfa = qfa(o, 1, n, x);
    	return tfa == x ? x : findset(o, tfa);
    }
    
    int main() {
    //	freopen("data.in", "r", stdin);
    	n = read(); int q = read();
    	for(int i = 1; i <= n; i++)
    		updatefa(rt[0], rt[0], 1, n, i, i), updatesiz(rt[0], rt[0], 1, n, i, 1);
    	for(int i = 1; i <= q; i++) {
    		int tp = read();
    		if(tp == 1) {
    			int a = findset(rt[i-1], read()), b = findset(rt[i-1], read());
    			if(a == b){ rt[i] = rt[i-1]; continue; }
    			int sa = qsiz(rt[i-1], 1, n, a), sb = qsiz(rt[i-1], 1, n, b);
    			if(sa < sb) swap(a, b), swap(sa, sb);
    			updatefa(rt[i], rt[i-1], 1, n, b, a);
    			updatesiz(rt[i], rt[i], 1, n, a, sa + sb);
    		}
    		if(tp == 2) {
    			int k = read();
    			rt[i] = rt[k];
    		}
    		if(tp == 3) {
    			int a = findset(rt[i-1], read()), b = findset(rt[i-1], read());
    //			printf("%d %d
    ", a, b);
    			puts(a == b ? "1" : "0");
    			rt[i] = rt[i-1];
    		}
    //		printf("ToT: %d
    ", ToT);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    计算机思维
    easyui增删改查前段代码
    文本相似度分析
    布隆过滤器
    SQL Server事务
    堆排序(Heapsort)
    游标
    存储过程
    触发器
    Thread部分总结以及小例子
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6360981.html
Copyright © 2011-2022 走看看