zoukankan      html  css  js  c++  java
  • AtcoderGrandContest 016 D.XOR Replace

    $ >AtcoderGrandContest space 016 D.XORspace Replace<$

    题目大意 :
    有两个长度为 (n) 的数组 (A, B) ,每次操作将 (A) 中的一个元素替换为 (A) 中所有元素的异或和,求最少几次操作可以从 (A) 变换到 (B)

    (1 leq n leq 10^5)

    解题思路 :

    设初始状态的异或和为 (S) ,第一次替换掉的数为 (x) ,容易发现新的数列的异或和为 (x) ,可以简单证明每一次的异或和等于上一次被替换的数。

    那么问题就转化为对于一个序列 (A)(A_{n+1} = S) ,第一次取出 (S) ,之后每一次替换掉某个数并取出它来替换别人,事实上每一个取出的数都会被放到其在 (B) 中的位置上。

    此时 (A) 数组就构成了若干个置换,最小花费就是置换的数量加上环上的点数 (-1) ,但是一个数可能会有多个合法的位置可以选,直接构造的话置换的数量可能不会优。

    但是观察发现如果两个置换存在数值相等的位置,那么可以通过交换 (next) 指针变成一个置换,所以只需要按照数值来合并联通块就能求出置换的最小数量,可以用并查集来维护。


    /*program by mangoyang*/
    #include<bits/stdc++.h>
    #define inf (0x7f7f7f7f)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
    	int f = 0, ch = 0; x = 0;
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    	for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    	if(f) x = -x;
    }
    const int N = 1000005;
    map<int, int> id;
    int fa[N], s1[N], s2[N], a[N], b[N], n, col, ans;
    inline int ask(int x){ return x == fa[x] ? x : fa[x] = ask(fa[x]); }
    inline void merge(int x, int y){
    	int p = ask(x), q = ask(y); if(p != q) fa[p] = q;
    }
    signed main(){
    	read(n);
    	for(int i = 1; i <= n; i++) read(a[i]), a[n+1] ^= a[i];
    	for(int i = 1; i <= n; i++) read(b[i]), b[n+1] ^= b[i];
    	for(int i = 1; i <= n + 1; i++) s1[i] = a[i], s2[i] = b[i];
    	sort(s1 + 1, s1 + n + 2), sort(s2 + 1, s2 + n + 2);
    	for(int i = 1; i <= n + 1; i++) if(s1[i] != s2[i]) return puts("-1"), 0;
    	for(int i = 1; i <= n; i++) if(a[i] != b[i]) ans++;
    	for(int i = 1; i <= n + 1; i++) fa[i] = i;
    	for(int i = 1; i <= n + 1; i++) if(a[i] != b[i]){
    		if(!id[a[i]]) id[a[i]] = ++col;
    		if(!id[b[i]]) id[b[i]] = ++col;
    		merge(id[a[i]], id[b[i]]);
    	}
    	if(!id[a[n+1]]) id[a[n+1]] = ++col;
    	if(!id[b[n+1]]) id[b[n+1]] = ++col;
    	for(int i = 1; i <= col; i++) if(fa[i] == i) ans++;
    	cout << ans - 1;
    	return 0;
    }
    
  • 相关阅读:
    b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释
    b2c项目基础架构分析(一)b2c 大型站点方案简述 已补充名词解释
    SQLite 创建自增长标识列
    【第三方支付】之微信支付
    【第三方登录】之微信第三方登录
    【第三方登录】之QQ第三方登录
    2014年互联网IT待遇【转载】
    有趣的程序
    python备忘录
    JAVA备忘录
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9813220.html
Copyright © 2011-2022 走看看