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

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

  • 相关阅读:
    @当你输入一个网址的时候,实际会发生什么?
    @Java魔法类——unsafer应用解析
    !@面试官:说说双亲委派模型?
    @JAVA字符串格式化
    @double精度比float低吗?
    @java类中资源加载顺序
    !@阿里资深架构师浅谈一个Java类的生命周期
    @String对象的那些事,几行代码就解释得清清楚楚
    @final、finally、finalize有什么区别?
    @35个Java代码优化的细节,你知道几个?
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14409657.html
Copyright © 2011-2022 走看看