AC日记——猴子 cogs 2043
2043. 猴子
★★ 输入文件:monkeya.in 输出文件:monkeya.out 简单对比
时间限制:1 s 内存限制:256 MB
【题目描述】
有n只猴子,第一只尾巴挂在树上,剩下的n-1只,要么被其他的猴子抓住,要么抓住了其他的猴子,要么两者均有。当然一只猴子最多抓两只另外的猴子,因为只有两只猴爪子嘛。现在给出这n只猴子抓与被抓的信息,并且在某个时刻可能某只猴子会放掉它左手或右手的猴子,导致某些猴子落在地上。求每只猴子落地的时间。
【输入格式】
第一行两个n,m,表示有n只猴子,并且总时间为m-1.
接下来n行,描述了每只猴子的信息,每行两个数,分别表示这只猴子左手和右手抓的猴子的编号,如果是-1,表示该猴子的那只手没抓其他的猴子。
再接下来M行,按时间顺序给出了一些猴子放手的信息,第1+n+i行表示i-1时刻某只猴子的放手信息,信息以两个数给出,前者表示放手的猴子的编号,后者表示其放的是哪只手,1左2右。
【输出格式】
共输出n行,第i行表示第i只猴子掉落的时刻,若第i只猴子道M-1时刻以后还没掉落,就输出-1。
【样例输入】
3 2
-1 3
3 -1
1 2
1 2
3 1
【样例输出】
-1
1
1
【提示】
n<=200000,m<=400000
【来源】
在此键入。
思路:
逆向并查集~;
这个题仔细读读可以发现这群猴子不按套路抓尾巴;
可能一只猴子的尾巴会被很多只猴子抓;
所以,这个题就成为了一个判断每个时间点连通性的问题;
判断图的联通性自然是用并查集呀;
但是,,,这个题貌似直接搞并查集不可行;
所以,,要加一点点乱搞的操作;
逆向并查集;
我们读入每个猴子的左右手抓的尾巴(建图);
然后,开始放手(删边);
放手的同时,把放手的操作记录下来;
然后,开始从第m-1秒到第0秒把放手的边加回去;
没加一条边就通过并查集判断一下图的联通性;
当当前块与1号联通时,就记录time;
怎么记录time呢?略略恶心,,就不讲了,,可以去看看我的代码(直白如话);
最后输出;
轻松ac;
来,上代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define maxn 200005 using namespace std; struct NodeType {
int l,r; bool li,ri;
};
struct NodeType node[maxn<<]; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int if_z,n,m,f[maxn],head[maxn],Time[maxn];
int cnt,do_s[maxn<<],do_w[maxn<<]; char Cget; bool if_[maxn],did[maxn]; inline void read_int(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
cnt++;
edge[cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt;
} int find(int x)
{
if(x==f[x]) return x;
f[x]=find(f[x]);
return f[x];
} void search(int now)
{
did[now]=true;
if(node[now].l!=-&&node[now].li)
{
int x=find(now),y=find(node[now].l);
if(x>y) swap(x,y);
if(x!=)
{
edge_add(x,y);
edge_add(y,x);
}
f[y]=x;
if(!did[node[now].l]) search(node[now].l);
}
if(node[now].r!=-&&node[now].ri)
{
int x=find(now),y=find(node[now].r);
if(x>y) swap(x,y);
if(x!=)
{
edge_add(x,y);
edge_add(y,x);
}
f[y]=x;
if(!did[node[now].r]) search(node[now].r);
}
} void search_(int now,int time_)
{
if_[now]=true;
Time[now]=time_;
for(int i=head[now];i;i=edge[i].next)
{
if(!if_[edge[i].to]) search_(edge[i].to,time_);
}
} int main()
{
freopen("monkeya.in","r",stdin);
freopen("monkeya.out","w",stdout);
memset(Time,-,sizeof(Time));
read_int(n),read_int(m);
m--;
for(int i=;i<=n;i++)
{
f[i]=i;
read_int(node[i].l);
read_int(node[i].r);
if(node[i].l!=-) node[i].li=true;
if(node[i].r!=-) node[i].ri=true;
}
for(int i=;i<=m;i++)
{
read_int(do_s[i]),read_int(do_w[i]);
if(do_w[i]==) node[do_s[i]].li=false;
else node[do_s[i]].ri=false;
}
for(int i=;i<=n;i++)
{
if(!did[i]) search(i);
}
for(int i=m;i>=;i--)
{
int x=do_s[i],y,x_,y_;
if(do_w[i]==) y=node[do_s[i]].l;
else y=node[do_s[i]].r;
if(y==-) continue;
x_=find(x),y_=find(y);
if(x_>y_) swap(x_,y_);
if(x_!=&&y_!=)
{
edge_add(x_,y_);
edge_add(y_,x_);
}
else if(x_!=&&y_==) Time[x_]=i;
else if(x_==&&y_!=) Time[y_]=i;
f[y_]=x_;
}
for(int i=;i<=n;i++)
{
if(Time[i]>=) search_(i,Time[i]);
}
for(int i=;i<=n;i++)
{
if(Time[i]<) printf("-1\n");
else printf("%d\n",Time[i]);
}
fclose(stdin);
fclose(stdout);
return ;
}
AC日记——猴子 cogs 2043的更多相关文章
- AC日记——codevs1688求逆序对
AC日记--codevs1688求逆序对 锵炬 掭约芴巷 枷锤霍蚣 蟠道初盛 到被他尽情地踩在脚下蹂躏心中就无比的兴奋他是怎么都 ㄥ|囿楣 定要将他剁成肉泥.挫骨扬灰跟随着戴爷这么多年刁梅生 圃鳋 ...
- 洛谷 P1653 == COGS 2043 猴子
P2107 可爱的猴子 时间限制:1000MS 空间限制:65535KB 问题描述: 树上有n只猴子.它们编号为 1 到n.1 号猴子用它的尾巴勾着树枝.剩下的猴子都被其他的猴子用手抓着.每只猴子的 ...
- AC日记——[NOIP2015]运输计划 cogs 2109
[NOIP2015] 运输计划 思路: 树剖+二分: 代码: #include <cstdio> #include <cstring> #include <iostrea ...
- AC日记——[WC2013]糖果公园 cogs 1817
[WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...
- AC日记——[国家集训队2011]旅游(宋方睿) cogs 1867
[国家集训队2011]旅游(宋方睿) 思路: 树链剖分,边权转点权: 线段树维护三个东西,sum,max,min: 当一个区间变成相反数时,sum=-sum,max=-min,min=-max: 来, ...
- AC日记——[国家集训队2010]小Z的袜子 cogs 1775
[国家集训队2010]小Z的袜子 思路: 传说中的莫队算法(优雅的暴力): 莫队算法是一个离线的区间询问算法: 如果我们知道[l,r], 那么,我们就能O(1)的时间求出(l-1,r),(l+1,r) ...
- AC日记——[ZJOI2009]假期的宿舍 cogs 1333
1333. [ZJOI2009] 假期的宿舍 ★★☆ 输入文件:zjoi09holiday.in 输出文件:zjoi09holiday.out 简单对比时间限制:1 s 内存限制:25 ...
- AC日记——[福利]可持久化线段树 cogs 2554
2554. [福利]可持久化线段树 ★★☆ 输入文件:longterm_segtree.in 输出文件:longterm_segtree.out 简单对比时间限制:3 s 内存限制:2 ...
- AC日记——[网络流24题]骑士共存 cogs 746
746. [网络流24题] 骑士共存 ★★☆ 输入文件:knight.in 输出文件:knight.out 简单对比时间限制:1 s 内存限制:128 MB 骑士共存问题 «问题描述: ...
随机推荐
- Python爬虫系列-Selenium详解
自动化测试工具,支持多种浏览器.爬虫中主要用来解决JavaScript渲染的问题. 用法讲解 模拟百度搜索网站过程: from selenium import webdriver from selen ...
- 拓展jQuery的serialize(),将form表单转化为json对象
jQuery 的 serialize() 方法经常会报 Uncaught TypeError: JSON.serializeObject is not a function 的错误, 原装的方法真的一 ...
- python爬虫基础11-selenium大全5/8-动作链
Selenium笔记(5)动作链 本文集链接:https://www.jianshu.com/nb/25338984 简介 一般来说我们与页面的交互可以使用Webelement的方法来进行点击等操作. ...
- python基本数据类型和简单用法
一.int 整形范围 How Big Is an int? In Python2, the size of an int was limited to 32 bits, which is enough ...
- GoF23种设计模式之结构型模式之代理模式
一.概述 为其他对象提供一种代理以控制对这个对象的访问. 二.适用性 1.远程代理(RemoteProxy):为一个对象在不同的地址空间土工局部代表. 2.虚代理(VirtualProxy):根据需要 ...
- stm32之PWM学习
下图是一个STM32普通PWM形成的图形原理说明 自动重装载寄存器(ARR)用于确定波形的频率(即周期).捕获比较寄存器(CCRx)(用于确定占空比的) PWM的工作过程如下:首先ARR寄存器里面的值 ...
- ADT操作实例
ps.1.put(rank,value) 把当前rank的元素的数值修改 2.get(rank)获取rank的元素 3.remove(value)把向量中value剔除掉 4.size()返回元素个数 ...
- Linux学习-Linux 的开机流程分析
开机流程一览 系统开机的经过可以汇整成底下的流程的: 加载 BIOS 的硬件信息与进行自我测试,并依据设定取得第一个可开机的装置; 读取并执行第一个开机装置内 MBR 的 boot Loader (亦 ...
- &与&&有什么区别?
一.简要说明 按位与:a&b是把a和b都转换成二进制数然后再进行与的运算: 逻辑与:a&&b就是当且仅当两个操作数均为 true时,其结果才为 true:只要有一个为零,a&a ...
- Android Studio安装踩坑
title: Android Studio安装踩坑 date: 2018-09-07 19:31:32 updated: tags: [Android,Android Studio,坑] descri ...