zoukankan      html  css  js  c++  java
  • BZOJ3674 可持久化并査集

    @(BZOJ)[可持久化并査集]

    Description

    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

    Sample Input

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

    Sample Output

    1
    0
    1
    

    Solution

    模板题.
    BZOJ上的数据傻到不行.
    还是去xsy上提交吧

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    
    const int N = 1 << 18, M = 1 << 18;
    int n;
    
    namespace Zeonfai
    {
    	inline int getInt()
    	{
    		int a = 0, sgn = 1;
    		char c;
    
    		while(! isdigit(c = getchar()))
    			sgn *= c == '-' ? -1 : 1;
    
    		while(isdigit(c))
    			a = a * 10 + c - '0', c = getchar();
    
    		return a * sgn;
    	}
    }
    
    struct persistentDisjointSet
    {
    	int rt[M], tp;
    
    	struct data
    	{
    		int pre, dep;
    	};
    
    	struct node
    	{
    		int suc[2];
    		data infr;
    	}nd[N * 18 + M * 18];
    
    	inline int newNode(int pre, int dep)
    	{
    		nd[tp].suc[0] = nd[tp].suc[1] = -1;
    		nd[tp].infr.pre = pre, nd[tp].infr.dep = dep;
    		return tp ++;
    	}
    
    	int build(int L, int R)
    	{
    		int u = newNode(L == R ? L : -1, 1);
    		
    		if(L == R)
    			return u;
    		
    		int mid = L + R >> 1;
    		nd[u].suc[0] = build(L, mid), nd[u].suc[1] = build(mid + 1, R);
    		return u;
    	}
    
    	inline void initialize()
    	{
    		memset(rt, -1, sizeof(rt));
    		tp = 0;
    		rt[0] = build(1, n);
    	}
    
    	int find(int L, int R, int u, int a)
    	{
    		if(L == R)
    			return u;
    
    		int mid = L + R >> 1;
    		
    		if(a <= mid)
    			return find(L, mid, nd[u].suc[0], a);
    		else
    			return find(mid + 1, R, nd[u].suc[1], a);
    	}
    
    	inline int access(int tm, int a)
    	{
    		while(int u = find(1, n, rt[tm], a))
    		{
    			if(nd[u].infr.pre == a)
    				return a;
    			
    			a = nd[u].infr.pre;
    		}
    	}
    
    	int newSegmentTree(int _u, int L, int R, int a, int b)
    	{
    		int u = tp ++;
    		nd[u] = nd[_u];
    		
    		if(L == R)
    			return u;
    		
    		int mid = L + R >> 1;
    
    		if((a >= L && a <= mid) || (b >= L && b <= mid))
    			nd[u].suc[0] = newSegmentTree(nd[_u].suc[0], L, mid, a, b);
    
    		if((a > mid && a <= R) || (b > mid && b <= R))
    			nd[u].suc[1] = newSegmentTree(nd[_u].suc[1], mid + 1, R, a, b);
    		
    		return u;
    	}
    
    	inline void merge(int tm, int a, int b)
    	{
    		int rtA = access(tm - 1, a), rtB = access(tm - 1, b);
    
    		if(rtA == rtB)
    		{
    			rt[tm] = rt[tm - 1];
    			return;
    		}
    
    		rt[tm] = newSegmentTree(rt[tm - 1], 1, n, rtA, rtB);
    		int u = find(1, n, rt[tm], rtA), v = find(1, n, rt[tm], rtB);
    
    		if(nd[u].infr.dep == nd[v].infr.dep)
    		{
    			++ nd[u].infr.dep;
    			nd[v].infr.pre = rtA;
    			return;
    		}
    
    		if(nd[u].infr.dep > nd[v].infr.dep)
    			nd[v].infr.pre = rtA;
    		else
    			nd[u].infr.pre = rtB;
    	}
    	
    	inline void accessHistory(int tm, int _tm)
    	{
    		rt[tm] = rt[_tm];
    	}
    
    	inline int query(int tm, int a, int b)
    	{
    		rt[tm] = rt[tm - 1];
    		int preA = access(tm, a), preB = access(tm, b);
    
    		if(preA == preB)
    			return 1;
    		else
    			return 0;
    	}
    }st;
    
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("BZOJ3674.in", "r", stdin);
    	freopen("BZOJ3674.out", "w", stdout);
    	#endif
    	
    	using namespace Zeonfai;
    
    	n = getInt();
    	int m = getInt(), lstAns = 0, tm = 0;
    	st.initialize();
    
    	while(m --)
    	{
    		int opt = getInt();
    
    		if(opt == 1)
    		{
    			int a = getInt() ^ lstAns, b = getInt() ^lstAns;
    			st.merge(++ tm, a, b);
    		}
    		else if(opt == 2)
    		{
    			int a = getInt() ^ lstAns;
    			st.accessHistory(++ tm, a);
    		}
    		else if(opt == 3)
    		{
    			int a = getInt() ^ lstAns, b = getInt() ^ lstAns;
    			printf("%d
    ", lstAns = st.query(++ tm, a, b));
    		}
    	}
    }
    
  • 相关阅读:
    黑马程序员:3分钟带你读懂C/C++学习路线
    大学毕业的你,满腔洪荒之力却找不到出口?
    从零基础到精通的前端学习路线
    Python学习笔记(2)——Python的函数、模块、包和库
    Python学习笔记(1)——Python的概述(Python的环境、变量、数据类型、基本运算)
    MATLAB优化——减少for的使用
    初识Python(windows)——下载、安装、使用
    高维数据稀疏表示-什么是字典学习(过完备词典)
    用1天快速上手org-mode(windows系统)
    零基础数据挖掘学习清单
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6681655.html
Copyright © 2011-2022 走看看