zoukankan      html  css  js  c++  java
  • Beauty of Trees

    题意:n个数,m个信息:L,R,k。每个信息表示a[L]^a[L+1]^a[L+2]^····^a[R]=k。如果第 i 个信息与前面 i-1 个信息矛盾的话就输出 i ,如果这m个信息都不矛盾的话,输出 -1

    题解:位运算多半要考虑二进制,这里将k分解成二进制形式。先令dp[i][j]表示第i个数之前(包括第i个数),二进制第j位为1的数的个数。如果k的二进制的第j位为1的话,说明区间[L,R]中这一位为1的数有奇数个(区间的数考虑成二进制),那么dp[L-1][j]和dp[R][j]的奇偶性相同,为啥呢?因为奇数减奇数等于偶数,偶数减偶数等于偶数~~~~~。同理可以分析出如果k的二进制的第j位为0的话,说明区间[L,R]中这一位为1的数有偶数个,那么dp[L-1][R]和dp[R][j]的奇偶性不同。小技巧出现啦^_^,对每一位开一个虚拟节点,用并查集管理,如果dp[L-1][j]和dp[R][j]的奇偶性不同,那么实点和虚点相连。奇偶性相同,就实点和实点相连,虚点和虚点相连。显然判断是否矛盾的方式也就自然出来了:奇偶性相同,但在并查集中确是实点和虚点连在了一起,说明矛盾。-----------------参考华中校赛题解

    #pragma warning(disable:4996)
    #include<cmath>
    #include<string>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mem(arr,in) memset(arr,in,sizeof(arr))
    using namespace std;
    
    const int maxn = 200010;
    
    int n, m;
    int pa[maxn][32];
    
    int Find(int a, int j) {
        if (pa[a][j] == a) return a;
        return pa[a][j] = Find(pa[a][j], j);
    }
    
    void Union(int a, int b, int j) {
        int x = Find(a, j);
        int y = Find(b, j);
        if (x != y) pa[x][j] = y;
        return;
    }
    
    void Inite() {
        for (int i = 0; i <= 2 * n + 1; i++) {
            for (int j = 0; j <= 30; j++) {
                pa[i][j] = i;
            }
        }
        return;
    }
    
    int main()
    {
        while (cin >> n >> m) {
            Inite();
            int cnt = 0;
            for (int i = 1; i <= m; i++) {
                int l, r, k;
                cin >> l >> r >> k;
                l--;
    
                bool flag = false;
                for (int j = 0; j <= 30; j++) {
                    int tp = k & (1 << j);
                    if(tp==0){
                        if (Find(l, j) == Find(r + n + 1, j) || Find(r, j) == Find(l + n + 1, j)){
                           printf("%d
    ", i);
                            flag = true;
                            break; 
                        }
                    }
                    else{
                        if(Find(l, j) == Find(r, j) || Find(l + n + 1, j) == Find(r + n + 1, j)){
                            printf("%d
    ", i);
                            flag = true;
                            break;
                        }
                    }
                    
                }
                if (flag) continue;
    
                cnt++;
                for (int j = 0; j <= 30; j++) {
                    int tp = k & (1 << j);
                    if (tp == 0) {
                        Union(l, r, j);
                        Union(l + n + 1, r + n + 1, j);
                    }
                    else {
                        Union(l, r + n + 1, j);
                        Union(l + n + 1, r, j);
                    }
                }
            }
            if (cnt == m) cout << "-1" << endl;
        }
        return 0;
    }
  • 相关阅读:
    环境部署(八):jenkins配置邮件通知
    环境部署(七):linux下Jenkins+Git+JDK持续集成
    环境部署(六):Git关联github
    Git基础使用教程
    环境部署(五):Linux下安装Gradle
    环境部署(四):Linux下查看JDK安装路径
    从百小度看人工智能
    手游开发Android平台周边工具介绍
    移动开发工具推荐
    关于方法论的闲扯
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9043158.html
Copyright © 2011-2022 走看看