zoukankan      html  css  js  c++  java
  • P5937 [CEOI1999]Parity Game

     (奇偶性真是太能整活了)

    找到第一句假话,显然在此之前需要找到一种方式存储先前给定的所有关系.

    为什么会想到"关系"呢?观察每一行给出的三元有序组,前两者是两个数值,最后一者表示某种状态,即奇偶性.应该可以联想到,两个数值表达的对象具有着此状态所表示的关系.

    也就是说,给定的数据是(对象A,对象B,A和B的关系),不要解读成了(数值,数值,一个未定的奇数/偶数),或者(对象,对象,一个未定的奇数/偶数),两个对象的某个共同数值有其他的处理方法(见借教室),而两个对象的关系使用并查集处理.在本题中,一个区间内所有1的数量即该区间所有数的和,表示区间数值的和使用前缀和数组:

      如果区间[a,b]中有偶数个1,那么(前缀和数组)s[b]-s[a-1]为偶数,即s[b]与s[a-1]奇偶性相同.

      如果区间[a,b]中有奇数个1,那么(前缀和数组)s[b]-s[a-1]为奇数,即s[b]与s[a-1]奇偶性不同.


    接下来的事情就是用拓展域并查集处理了(也有人把这个叫种类并查集).观察数据范围,会想到离散化的.

    实际上并不需要创建这个前缀和数组.因为并不需要对其进行任何操作,也没有可用的数据.注意区间[a,b]对应的对象是s[a-1]和s[b].

    #include <algorithm>
    #include <cstdio>
    #include <string>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    struct S{
        int l, r, v;
    };
    deque<S> q;
    int n, m, ind, ans, fa[10010], dis[10010];
    
    void discrete() {
        sort(dis + 1, dis + 1 + ind);
        ind = unique(dis + 1, dis + 1 + ind) - dis - 1;
    }
    int query(int x) { return lower_bound(dis + 1, dis + 1 + ind, x) - dis; }
    int get(int x){if(fa[x] == x) return x; return fa[x] = get(fa[x]);}
    void merge(int x, int y) {fa[get(y)] = fa[get(x)];}
    
    int main(){
        cin >> n >> m;
        ans = m;
        for(int i = 1; i <= m; i++) {
            int a, b;
            string c;
            cin >> a >> b >> c;
            a--;
            q.push_back({a, b, c == "even" ? 1 : -1});
            dis[++ind] = a, dis[++ind] = b;
        }
        discrete();
        for(int i = 1; i <= ind * 2; i++) fa[i] = i;
    
        while(!q.empty()){
            S cur = q.front();
            q.pop_front();
            int x = query(cur.l), y = query(cur.r), z = cur.v;
    
            if(z == -1){    // odd, diff
                if(get(x) == get(y)){ans = m - q.size() - 1; break;}
                merge(y, x + ind), merge(x , y + ind);
            }else{          // even, same
                if(get(x) == get(y + ind)){ans = m - q.size() - 1; break;}
                merge(x, y), merge(x + ind, y + ind);
            }
        }
    
        cout << ans << endl;
    
        return 0;
    }
    P5937

    玩奇偶性的还有这题.可以看出来奇偶性可以往前缀和上面想想.

  • 相关阅读:
    LeetCode 264. Ugly Number II
    LeetCode 231. Power of Two
    LeetCode 263. Ugly Number
    LeetCode 136. Single Number
    LeetCode 69. Sqrt(x)
    LeetCode 66. Plus One
    LeetCode 70. Climbing Stairs
    LeetCode 628. Maximum Product of Three Numbers
    Leetcode 13. Roman to Integer
    大二暑假周进度报告03
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14409657.html
Copyright © 2011-2022 走看看