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

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Java使用POI-TL和JFreeChart动态生成Word报告

《Java使用POI-TL和JFreeChart动态生成Word报告》本文介绍了使用POI-TL和JFreeChart生成包含动态数据和图表的Word报告的方法,并分享了实际开发中的踩坑经验,通过代码... 目录前言一、需求背景二、方案分析三、 POI-TL + JFreeChart 实现3.1 Maven

Java导出Excel动态表头的示例详解

《Java导出Excel动态表头的示例详解》这篇文章主要为大家详细介绍了Java导出Excel动态表头的相关知识,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录前言一、效果展示二、代码实现1.固定头实体类2.动态头实现3.导出动态头前言本文只记录大致思路以及做法,代码不进

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

基于Java实现模板填充Word

《基于Java实现模板填充Word》这篇文章主要为大家详细介绍了如何用Java实现按产品经理提供的Word模板填充数据,并以word或pdf形式导出,有需要的小伙伴可以参考一下... Java实现按模板填充wor编程d本文讲解的需求是:我们需要把数据库中的某些数据按照 产品经理提供的 word模板,把数据

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字