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

相关文章

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

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

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S