当前位置: 首页 > news >正文

[ NOI 2001 ] 食物链

\(\\\)

Description


有三类动物 \(A,B,C\),满足\(A\)\(B\)\(B\)\(C\)\(C\)\(A\)

现有 \(N\) 个动物,以 \(1 - N\) 编号。每个动物都是 \(A,B,C\) 中的一种。

有人用两种说法对这 \(N\) 个动物所构成的食物链关系进行描述:

第一种说法是“1 X Y”,表示 X 和 Y 是同类。

第二种说法是“2 X Y”,表示 X 吃 Y 。

此人对 N 个动物,用上述两种说法,一句接一句地说出 K 句话,这 K 句话有的是真

的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。

  • 当前的话与前面的某些真的话冲突,就是假话

  • 当前的话中 X 或 Y 比 N 大,就是假话

  • 当前的话表示 X 吃 X,就是假话

你的任务是根据给定的 N 和 K 句话,输出假话的总数。

  • \(n\le 5\times 10^4,K\le 10^5\)

\(\\\)

Solution


扩展域的并查集。

建立三个域,分别为 \(x,x+n,x+2n\)

如果 \(x,y\) 在一个集合里,代表 \(x,y\) 是同类。

如果 \(x+n,y\) 在一个集合里,代表 \(y\)\(x\) 的捕食对象。

如果 \(x+2n,y\) 在一个集合里,代表 \(y\)\(x\) 的天敌。

注意这里以 \(x\) 为中心构建的集合,具有代表意义。

\(x+n,x+2n\) 只作为中转点,所在的集合中所有 \(n\) 范围内的点含义相同。

\(\\\)

对于同类语句:

如果某一个是另一个的天敌或捕食对象 \(GG\)

否则合并两者的三个集合。

\(\\\)

对于捕食语句 \((x\) 捕食 \(y)\)

如果两者是同类 \(GG\)

如果 \(y\)\(x\) 的天敌 \(GG\)

因为只有三个集合,所以合并:

  • \(x\)\(y+2n\)\(x\)\(y\) 的天敌。

  • \(x+n\)\(y\)\(y\)\(x\) 的捕食对象。

  • \(x+2n\)\(y+n\) :第三类关系,\(x\) 的天敌一定是 \(y\) 的捕食对象。

\(\\\)

在这个过程中应该有一些思考。

合并的有效对象其实一直是 \([1,n]\) 范围内的点,而我们只是通过等价关系借用了两个扩展域合并。

所有的查询也是借用定义,实则查的其实还是 \([1,n]\) 范围内的点。

\(\\\)

Code


#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 150010
#define R register
#define gc getchar
using namespace std;

inline int rd(){
  int x=0; bool f=0; char c=gc();
  while(!isdigit(c)){if(c=='-')f=1;c=gc();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
  return f?-x:x;
}

int n,m,ans,f[N];

inline void reset(){for(R int i=1;i<N;++i) f[i]=i;}

int find(int x){return x==f[x]?x:f[x]=find(f[x]);}

inline void merge(int x,int y){f[find(x)]=find(y);}

int main(){
  n=rd(); m=rd(); reset();
  for(R int i=1,op,x,y;i<=m;++i){
    op=rd(); x=rd(); y=rd();
    if(x>n||y>n){++ans;continue;}
    if(op==1){
      if(find(x)==find(y+n)||find(x)==find(y+2*n)){++ans;continue;}
      merge(x,y); merge(x+n,y+n); merge(x+n*2,y+n*2);
    }
    else{
      if(x==y){++ans;continue;}
      if(find(x)==find(y)||find(x+2*n)==find(y)){++ans;continue;}
      merge(x,y+n*2); merge(x+n,y); merge(x+n*2,y+n);
    }
  }
  printf("%d\n",ans);
  return 0;
}

转载于:https://www.cnblogs.com/SGCollin/p/9917515.html

相关文章:

  • tomcat8 安装部署--一键版本
  • 【SSH网上商城项目实战25】使用java email给用户发送邮件
  • extjs 之columntree 自定义分页工具条
  • javascript基础修炼(9)——MVVM中双向数据绑定的基本原理
  • python lambda的详细介绍
  • 字典变成有序字典
  • Vbs脚本编程简明教程之六
  • iptables的snat与dnat
  • 传Windows 7 正式版明年6月发布
  • 软件名称集合
  • 在Hyper-V下安装Centos Linux系统的网卡驱动问题
  • 数据库连接池问题 Max Pool Size
  • 0228_2012深圳试题_网络配置部分
  • WPFのclipToBounds与maskToBounds的区别
  • 大家多开发点uwp吧
  • Angular2开发踩坑系列-生产环境编译
  • docker python 配置
  • extract-text-webpack-plugin用法
  • Java 23种设计模式 之单例模式 7种实现方式
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • java中具有继承关系的类及其对象初始化顺序
  • leetcode46 Permutation 排列组合
  • leetcode讲解--894. All Possible Full Binary Trees
  • mysql innodb 索引使用指南
  • node.js
  • python docx文档转html页面
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • Terraform入门 - 1. 安装Terraform
  • windows下如何用phpstorm同步测试服务器
  • 从零开始在ubuntu上搭建node开发环境
  • 如何设计一个比特币钱包服务
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 算法-图和图算法
  • 我感觉这是史上最牛的防sql注入方法类
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 移动端 h5开发相关内容总结(三)
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • MPAndroidChart 教程:Y轴 YAxis
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ![CDATA[ ]] 是什么东东
  • #define与typedef区别
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (0)Nginx 功能特性
  • (1)(1.13) SiK无线电高级配置(五)
  • (七)Knockout 创建自定义绑定
  • (四) 虚拟摄像头vivi体验
  • (转)Oracle存储过程编写经验和优化措施
  • .describe() python_Python-Win32com-Excel
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • .net反混淆脱壳工具de4dot的使用
  • @Autowired多个相同类型bean装配问题
  • @RequestBody与@ModelAttribute
  • [ CTF ] WriteUp-2022年春秋杯网络安全联赛-冬季赛
  • [2017][note]基于空间交叉相位调制的两个连续波在few layer铋Bi中的全光switch——