BZOJ 2049 动态树-模板题

2024-08-23 14:38
文章标签 动态 模板 bzoj 2049

本文主要是介绍BZOJ 2049 动态树-模板题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BZOJ 2049:[Sdoi2008]Cave 洞穴勘测

 

辉辉有一台监测仪器可以实时将通道的每一次改变状况在辉辉手边的终端机上显示:如果监测到洞穴u和洞穴v之间出现了一条通道,终端机上会显示一条指令 Connect u v 。如果监测到洞穴u和洞穴v之间的通道被毁,终端机上会显示一条指令 Destroy u v 。经过长期的艰苦卓绝的手工推算,辉辉发现一个奇怪的现象:无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径。因而,辉辉坚信这是由于某种本质规律的支配导致的。因而,辉辉更加夜以继日地坚守在终端机之前,试图通过通道的改变情况来研究这条本质规律。然而,终于有一天,辉辉在堆积成山的演算纸中崩溃了……他把终端机往地面一砸(终端机也足够坚固无法破坏),转而求助于你,说道:“你老兄把这程序写写吧”。辉辉希望能随时通过终端机发出指令 Query u v,向监测仪询问此时洞穴u和洞穴v是否连通。现在你要为他编写程序回答每一次询问。已知在第一条指令显示之前,JSZX洞穴群中没有任何通道存在。

Input

第一行为两个正整数n(10000)和m(200000),分别表示洞穴的个数和终端机上出现过的指令的个数。以下m行,依次表示终端机上出现的各条指令。每行开头是一个表示指令种类的字符串s("Connect”、”Destroy”或者”Query”,区分大小写),之后有两个整数u和v (1≤u, v≤n且u≠v) 分别表示两个洞穴的编号。

Output

对每个Query指令,输出洞穴u和洞穴v是否互相连通:是输出”Yes”,否则输出”No”。(不含双引号)

Sample Input

Sample Output

200    5

Query      123  127

Connect     123  127

Query       123  127

Destroy     127  123

Query           123  127

3       5

Connect     1     2

Connect     3     1

Query       2     3

Destroy     1     3

Query           2   3

No

Yes

No

 

Yes

No

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 10010
struct Node {Node *ch[2],*fa;int rev,value;Node(){ch[0] = ch[1] = fa = NULL;rev = 0;}Node(int v){ch[0] = ch[1] = fa = NULL;rev = 0; value = v;}int lr_ch(Node *(&node)) {this -> push_down();return ch[1] == node;}void link_ch(Node *(&node),int d) {ch[d] = node;if(node!=NULL) node -> fa = this;}void push_rev(Node *(&node)) {swap(node->ch[0],node->ch[1]);node->rev ^= 1;}void push_down() {if(rev == 0) return;if(ch[0] != NULL) push_rev(ch[0]);if(ch[1] != NULL) push_rev(ch[1]);rev = 0;}
}*root,*nod[N];
inline int is_Root(Node *(&node));// 一定要注意splay之前 小棵splay树上根node之间的节点下放
void push_Path(Node *(&node)){Node *stack[N],*now = node;int top = 0;
while(!is_Root(now)){ 
stack[++top] = now;now  =  now -> fa;
}    
stack[++top] = now;while(top != 0)   stack[top--] -> push_down();
}
//单旋操作,注意与splay模板的区别
void rotate(Node *(&node),int d) {Node *ff = node -> fa -> fa;Node *f = node -> fa;f -> link_ch(node->ch[d],d^1);//当ff为"天花板"时,"天花板"是没有孩子的if(!is_Root(f))    ff->link_ch(node,ff->lr_ch(f));else            node->fa = ff;node -> link_ch(f,d);
}
//注意splay的写法,别用函数递归,防止爆栈
void splay(Node *(&node)){push_Path(node);while(!is_Root(node)){node -> fa -> push_down();  node -> push_down();if(is_Root(node->fa)){rotate(node,node->fa->ch[0]==node);return;}int  b1 = (node->fa->fa->ch[0]==node->fa);int  b2 = (node->fa->ch[0]==node);if(b1==b2)   rotate(node->fa,b2);else         rotate(node,b2);rotate(node,b1);}
}
//判断node节点是否为一小棵splay树的根
inline int is_Root(Node *(&node)) {if(node->fa->ch[0]==node) return 0;if(node->fa->ch[1]==node) return 0;return 1;
}
//access操作,打通node节点与"天花板"root
void access(Node *(&node)) {Node *up = node,*down = NULL;while(up != root) {splay(up);up -> push_down();up -> ch[1] = down;down = up;  up = up -> fa;}
}
//将大森林的树根换成node!
void re_Root(Node *(&node)) {access(node);splay(node);node -> push_rev(node);
}
//要记住: link操作的前提是link后 不能形成环
void link(Node *(&node1),Node *(&node2)) {re_Root(node1);node1 -> fa = node2;access(node1);
}
//要记住: cut操作node1必须与node2有边存在
void cut(Node *(&node1),Node *(&node2)) {re_Root(node2);access(node1);splay(node1);node2 -> fa = root;node1 -> push_down();node1 -> ch[0] = NULL;
}
//判断node1余node2是否在同一棵小splay树中
int judge(Node *node1,Node *node2){while(node1->fa!=root) node1 = node1 -> fa;while(node2->fa!=root) node2 = node2 -> fa;return node1==node2;
}
//初始化所有节点与"天花板"
void init(int n) {root = new Node(-1);for(int i=1;i<=n;i++) {nod[i] = NULL;nod[i] = new Node(i);nod[i] -> fa = root;}
}
//释放节点所占空间;但是注意nod[i]节点没有被初始化
void delet(Node *(&node)){if(node==NULL) return;delet(node->ch[0]);delet(node->ch[1]);delete node;  node = NULL;
}
int main() {int n,m,x,y;char s[25];while(~scanf("%d%d",&n,&m)){init(n);for(int i = 1;i<=m;i++){scanf("%s%d%d",s,&x,&y);if(s[0]=='C') link(nod[x],nod[y]);if(s[0]=='D') cut(nod[x],nod[y]);if(s[0]=='Q') printf("%s\n",judge(nod[x],nod[y])?"Yes":"No");}delet(root);}return 0;
}


这篇关于BZOJ 2049 动态树-模板题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1099667

相关文章

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

SpringBoot实现Kafka动态反序列化的完整代码

《SpringBoot实现Kafka动态反序列化的完整代码》在分布式系统中,Kafka作为高吞吐量的消息队列,常常需要处理来自不同主题(Topic)的异构数据,不同的业务场景可能要求对同一消费者组内的... 目录引言一、问题背景1.1 动态反序列化的需求1.2 常见问题二、动态反序列化的核心方案2.1 ht

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

Java如何根据word模板导出数据

《Java如何根据word模板导出数据》这篇文章主要为大家详细介绍了Java如何实现根据word模板导出数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... pom.XML文件导入依赖 <dependency> <groupId>cn.afterturn</groupId>

Python Selenium动态渲染页面和抓取的使用指南

《PythonSelenium动态渲染页面和抓取的使用指南》在Web数据采集领域,动态渲染页面已成为现代网站的主流形式,本文将从技术原理,环境配置,核心功能系统讲解Selenium在Python动态... 目录一、Selenium技术架构解析二、环境搭建与基础配置1. 组件安装2. 驱动配置3. 基础操作模

Python中Flask模板的使用与高级技巧详解

《Python中Flask模板的使用与高级技巧详解》在Web开发中,直接将HTML代码写在Python文件中会导致诸多问题,Flask内置了Jinja2模板引擎,完美解决了这些问题,下面我们就来看看F... 目录一、模板渲染基础1.1 为什么需要模板引擎1.2 第一个模板渲染示例1.3 模板渲染原理二、模板

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

利用Python打造一个Excel记账模板

《利用Python打造一个Excel记账模板》这篇文章主要为大家详细介绍了如何使用Python打造一个超实用的Excel记账模板,可以帮助大家高效管理财务,迈向财富自由之路,感兴趣的小伙伴快跟随小编一... 目录设置预算百分比超支标红预警记账模板功能介绍基础记账预算管理可视化分析摸鱼时间理财法碎片时间利用财