zoukankan      html  css  js  c++  java
  • [BZOJ3674]可持久化并查集加强版

    [BZOJ3674]可持久化并查集加强版

    试题描述

    自从zkysb出了可持久化并查集后……
    hzwer:乱写能AC,暴力踩标程
    KuribohG:我不路径压缩就过了!
    ndsf:暴力就可以轻松虐!
    zky:……

    n个集合 m个操作
    操作:
    1 a b 合并a,b所在集合
    2 k 回到第k次操作之后的状态(查询算作操作)
    3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
    请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0
    0<n,m<=2*10^5

    输入

    见“试题描述

    输出

    见“试题描述

    输入示例

    5 6
    1 1 2
    3 1 2
    2 1
    3 0 3
    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 200010
    #define maxnode 14400000
    
    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);
    	bool lst = 0;
    	for(int i = 1; i <= q; i++) {
    		int tp = read();
    		if(tp == 1) {
    			int a = findset(rt[i-1], read() ^ lst), b = findset(rt[i-1], read() ^ lst);
    			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() ^ lst;
    			rt[i] = rt[k];
    		}
    		if(tp == 3) {
    			int a = findset(rt[i-1], read() ^ lst), b = findset(rt[i-1], read() ^ lst);
    //			printf("%d %d
    ", a, b);
    			lst = a == b; printf("%d
    ", lst);
    			rt[i] = rt[i-1];
    		}
    //		printf("ToT: %d
    ", ToT);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    PID控制原理和算法
    Android 按钮长按下去重复执行某个动作,放开后停止执行动作
    最小二乘法拟合非线性函数及其Matlab/Excel 实现
    Android 基于蓝牙的方向控制器
    Android/Java 中的 String, StringBuffer, StringBuilder的区别和使用
    input 只允许输入数字
    java scoket编程
    RBAC权限管理
    整理大型网站架构必知必会的几个服务器知识
    Java中Class<T>与Class<?>的区别
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6360984.html
Copyright © 2011-2022 走看看