• POJ 1733 Parity game 【带权并查集】+【离散化】


    <题目链接>

    题目大意:

    一个由0,1组成的序列,每次给出一段区间的奇偶,问哪一条信息不合法。

    解题分析:

    我们用s[i]表示前i个数的前缀和,那么a b even意味着s[b]和s[a-1]的奇偶性相同。a b odd意味着s[b]与s[a-1]的奇偶性不同。于是我们根据奇偶性的不同,用并查集依次处理他们之间的关系。当某条信息出现与并查集中记录的信息不符合时,则此信息不合法。

    由于该序列的长度达到了1e9,并且查询次数只有5000次,所以我们需要对查询的区间进行离散化,否则存不下,数据比较小,用map离散化即可,也不会很慢。

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map> 
    using namespace std;
    
    #define RP(i,s,t) for(int i=s;i<=t;i++)
    #define fastIO ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    const int N = 1e4 + 5;
    
    int n, m, tot,fa[N + 10], w[N + 10];
    map<int,int>mp;
    
    int find(int x){
      if(x==fa[x])return x;
      int tmp=fa[x];
      fa[x]=find(fa[x]);
      w[x]=(w[x]+w[tmp]+2)%2;         //带权并查集关系的转移
      return fa[x];
    }
    inline bool Union(int a,int b,int x){
      int ra=find(a),rb=find(b);
      if(ra!=rb){
        fa[ra]=rb;
        w[ra]=(w[a]-w[b]+x+2)%2;
      }else{
        if((w[a]-w[b]+2)%2!=x)return false;            //与之前建立的关系奇偶性不符,则表示出现冲突 
      }return true;
    }
    int main() {
      fastIO
      cin >> n >> m;
      RP(i, 1, N + 5) fa[i] = i, w[i] = 0;
      int ans=0;
      RP(i,1,m){
        int a,b;string s;
        cin>>a>>b>>s;--a;                            //因为根据的是前缀和的奇偶性,所以这里a要记得-1 
        if(!mp[a])mp[a]=++tot;        //map用来离散化 
        if(!mp[b])mp[b]=++tot;
        int k=(s=="odd")?1:0;                        //odd才是奇,容易搞错 
        if(Union(mp[a],mp[b],k))ans++;
        else break;
      }cout<<ans<<'
    ';
    }

    2018-10-02

  • 相关阅读:
    windows7 dos修改mysql root密码
    Windows7 安装完成mysql dos启动服务出现服务名称无效
    windows 环境下.Net使用Redis缓存
    SQLSERVER 使用 ROLLUP 汇总数据,实现分组统计,合计,小计
    Web Form 和asp.net mvc 差别
    SQL Server如何编辑超过前200行的数据
    附加数据库失败,操作系统错误 5:"5(拒绝访问。)"的解决办法
    MVC 架构
    关于打印代码
    关于WCF一些基础。
  • 原文地址:https://www.cnblogs.com/00isok/p/9738887.html
Copyright © 2020-2023  润新知