【HDU4010】【LCT】Query on The Trees
There
are N nodes, each node will have a unique weight Wi. We
will have four kinds of operations on it and you should solve them
efficiently. Wish you have fun!
For
each case, the first line contains only one integer N.(1 ≤ N ≤
300000) The next N‐1 lines each contains two integers x, y which means
there is an edge between them. It also means we will give you one tree
initially.
The next line will contains N integers which means the weight Wi of each node. (0 ≤ Wi ≤ 3000)
The
next line will contains an integer Q. (1 ≤ Q ≤ 300000) The next Q
lines will start with an integer 1, 2, 3 or 4 means the kind of this
operation.
1. Given two integer x, y, you should make a new edge
between these two node x and y. So after this operation, two trees will
be connected to a new one.
2. Given two integer x, y, you should
find the tree in the tree set who contain node x, and you should make
the node x be the root of this tree, and then you should cut the edge
between node y and its parent. So after this operation, a tree will be
separate into two parts.
3. Given three integer w, x, y, for the x, y and all nodes between the path from x to y, you should increase their weight by w.
4.
Given two integer x, y, you should check the node weights on the path
between x and y, and you should output the maximum weight on it.
each query you should output the correct answer of it. If you find this
query is an illegal operation, you should output ‐1.
You should output a blank line after each test case.
1 2
2 4
2 5
1 3
1 2 3 4 5
6
4 2 3
2 1 2
4 2 3
1 3 5
3 2 1 4
4 1 4
-1
7
We define the illegal situation of different operations:
In first operation: if node x and y belong to a same tree, we think it's illegal.
In second operation: if x = y or x and y not belong to a same tree, we think it's illegal.
In third operation: if x and y not belong to a same tree, we think it's illegal.
In fourth operation: if x and y not belong to a same tree, we think it's illegal.
/*
唐代白居易
《浪淘沙·借问江潮与海水》
借问江潮与海水,何似君情与妾心?
相恨不如潮有信,相思始觉海非深。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#include <stack>
#define LOCAL
const int INF = 0x7fffffff;
const int MAXN = + ;
const int maxnode = ;
const int maxm= * + ;
using namespace std; struct Link_Cut_Tree{
struct Node{//splay节点
int val, add;
int Max, turn;
Node *parent, *ch[];
}node[MAXN], *null;
Node *pos;//计数
Node *tmp[MAXN]; void change(Node *u){access(u)->turn ^= ;}//注意因为x是在右子树要翻转
void init(){
//循环指针
null = node;
null->parent = null->ch[] = null->ch[] = null;
null->Max = null->val = -INF;
null->add = null->turn = ; pos = node + ;
}
//用这种方法实现快捷方便.便于直接查找
Node *NEW(int x){
pos->Max = pos->val = x;
pos->turn = pos->add = ;
pos->parent = pos->ch[] = pos->ch[] = null;
return pos++;
}
//判断x是否是根,注意这个是判断是否是splay的根,而不是lct的根
bool is_root(Node *x){
if (x == null || (x->parent->ch[] != x && x->parent->ch[] != x)) return ;
return ;
}
//标记下传
void pushdown(Node *x){
if (x == null) return;
if (x->turn){//翻转标记 if (x->ch[] != null) x->ch[]->turn ^= ;
if (x->ch[] != null) x->ch[]->turn ^= ;
swap(x->ch[], x->ch[]);//交换左右子树.
x->turn = ;
}
//权值标记
if (x->add){
if (x->ch[] != null){
x->ch[]->val += x->add;
x->ch[]->Max += x->add;
x->ch[]->add += x->add;
}
if (x->ch[] != null){
x->ch[]->val += x->add;
x->ch[]->Max += x->add;
x->ch[]->add += x->add;
}
x->add = ;
}
return;
}
//更新
void update(Node *x){
if (x == null) return;
x->Max = max(x->val, max(x->ch[]->Max, x->ch[]->Max));
} //d = 0为左旋,否则为右旋
void rotate(Node *x, int d){
if (is_root(x)) return;//是根就不转
Node *y = x->parent;
y->ch[d ^ ] = x->ch[d];
if (x->ch[d] != null) x->ch[d]->parent = y;
x->parent = y->parent;
if (y != null){
if (y == y->parent->ch[]) y->parent->ch[] = x;
else if (y == y->parent->ch[]) y->parent->ch[] = x;
}
x->ch[d] = y;
y->parent = x;
update(y);
}
//将x转到根
void splay(Node *x){
//带标记splay的伸展操作
//将从顶部到根部的节点全部pushdown
int cnt = ;
tmp[] = x;
for (Node *y = x; !is_root(y); y = y->parent) tmp[cnt++] = y->parent;
while (cnt) pushdown(tmp[--cnt]); while (!is_root(x)){
Node *y = x->parent;
if (is_root(y)) rotate(x, (x == y->ch[]));
else {
int d = (y->parent->ch[] == y);
if (y->ch[d] == x) rotate(x, d ^ );
else rotate(y, d);
rotate(x, d);
}
}
update(x);
}
//lct的访问操作,也是核心代码
Node *access(Node *u){
Node *v = null;
while (u != null){//非lct根,总是放在右边
splay(u);
v->parent = u;
u->ch[] = v;
update(u);
v = u;
u = u->parent;
}
return v;
}
//合并操作
void merge(Node *u, Node *v){
//if (u->val == 2 && v->val == 5)
//printf("%d\n", u->ch[0]->val);
//注意u为根
access(u);
splay(u); u->turn = ;//翻转,因为在access之后,u已经成为splay中深度最大的点,因此右子树为null,此时要成为根就要翻转
u->parent = v;
}
void cut(Node *u){
access(u);
splay(u);
//注意到u为根,自然深度最小,分离出来
u->ch[]->parent = null;
u->ch[] = null;
update(u);
}
//找根,不是真根
Node *findroot(Node *u){
access(u);//不仅要打通,而且要让u成为根
splay(u); while (u->parent != null) u = u->parent;
return u;
}
//判断u和v是否在同一个子树中
bool check(Node *u, Node *v){
while (u->parent != null) u = u->parent;
while (v->parent != null) v = v->parent;
return (u == v);
}
}splay;
int u[MAXN],v[MAXN];
int n, m;
/*struct Node{
Node *ch[2];
int val;
};
Node* rotate(Node *t, int d){
Node *p = t->ch[d ^ 1];
t->ch[d ^ 1] = p->ch[d];
p->ch[d] = t;
t = p;
return t;
}*/
void init(){
splay.init();
for (int i = ; i < n; i++) scanf("%d%d", &u[i], &v[i]);
//各点权值
for (int i = ; i <= n; i++){
int t;
scanf("%d", &t);
splay.NEW(t);
}
for (int i = ; i < n; i++) {
// if (i == 3)
// printf("");
splay.merge(splay.node + u[i], splay.node + v[i]);
//printf("%d\n", splay.node[2].ch[0]->val);
}
//printf("%d", splay.check(splay.node + 4, splay.node + 5));
}
void work(){
scanf("%d", &m);
for (int i = ; i <= m; i++){
int t;
scanf("%d", &t);
if (t == ){//连接两点
int u, v;
scanf("%d%d", &u, &v);
//判断是否在同一个lct树内
if (splay.check(splay.node + u, splay.node + v)){
//printf("%d ", i);
printf("-1\n");
continue;
}
splay.merge(splay.node + u, splay.node + v);
}else if (t == ){
int u, v;
scanf("%d%d", &u, &v);
//分离两颗树
if (u == v || !splay.check(splay.node + u, splay.node + v)){
//printf("%d ", i);
printf("-1\n");
continue;
}
//转根再分离
splay.change(splay.node + u);//注意这个根是原树的根不是lct的根
splay.cut(splay.node + v);
}else if (t == ){
int u, v, w;
scanf("%d%d%d", &w, &u, &v);
//不再同一个树内自然无法更新
if (!splay.check(splay.node + u, splay.node + v)){
//printf("%d ", i);
printf("-1\n");
continue;
}
splay.change(splay.node + u);
splay.access(splay.node + v);
//将u换为真根,则u所在的splay都是v-u路径上的节点
Link_Cut_Tree::Node *q = splay.findroot(splay.node + v);
q->add += w;
q->Max += w;
q->val += w;
}else {//查询操作
int u, v;
scanf("%d%d", &u, &v);
if (!splay.check(splay.node + u, splay.node + v)){
//printf("%d ", i);
printf("-1\n");
continue;
}
//先换根
splay.change(splay.node + u);
splay.access(splay.node + v);
printf("%d\n", splay.findroot(splay.node + v)->Max);
}
}
printf("\n");
} int main (){ //scanf("%d", &n);
while (scanf("%d", &n) != EOF){
init();
work();
}
return ;
}
【HDU4010】【LCT】Query on The Trees的更多相关文章
- BZOJ2157 旅游 【树剖 或 LCT】
题目 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径. ...
- bzoj 4817: [Sdoi2017]树点涂色【树链剖分+LCT】
非常妙的一道题. 首先对于操作一"把点x到根节点的路径上所有的点染上一种没有用过的新颜色",长得是不是有点像LCT中的access操作?进而发现,如果把同一颜色的点连起来作为LCT ...
- 【UOJ274】【清华集训2016】温暖会指引我们前行 LCT
[UOJ274][清华集训2016]温暖会指引我们前行 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很 ...
- 【Spring Data 系列学习】Spring Data JPA @Query 注解查询
[Spring Data 系列学习]Spring Data JPA @Query 注解查询 前面的章节讲述了 Spring Data Jpa 通过声明式对数据库进行操作,上手速度快简单易操作.但同时 ...
- 【BZOJ3669】【Noi2014】魔法森林(Link-Cut Tree)
[BZOJ3669][Noi2014]魔法森林(Link-Cut Tree) 题面 题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n ...
- 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付
微信支付教程系列之扫码支付 今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(中)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- 【SQL篇章--DATABASE/EVENTS】
[SQL篇章][SQL语句梳理 :--基于MySQL5.6][已梳理:DATABASE/EVENTS][会坚持完善] 目录: 1. Data Definition Statements: 1.1 ...
- 【ipv6惹的祸】curl 超时
偶然发现 最近在公司日志平台 总是可以看到很多关于php curl的错误信息 Operation timed out after 0 milliseconds with 0 out of 0 byte ...
- 最全的MySQL基础【燕十八传世】
1.课前准备! 开启mysql服务:1).配置环境变量;2).net start mysql 将该sql文件导入到你的数据库中,以下所有操作都是基于该数据库表操作的!!! [此笔记是本人看着视频加上自 ...
随机推荐
- Linux学习笔记2——Linux中常用文件目录操作命令
ls 显示文件和目录列表 -l 列出文件的详细信息 -a 列出当前目录所有文件,包含隐藏文件 mkdir 创建目录 -p 父目录不存在情况下先生成父目录 cd 切换目录 touch 生成一个空文件 e ...
- Objective-c知识小结
1.创建一个类产生.h和.m两个文件,.h中对用到的变量.方法作声明,.m文件中实现,导入时只导入.h文件,如果直接把方法写在.m文件中,未在.h文件中进行声明,则是私有方法 2.@interfac ...
- 怎么把GPUImageFIlter处理过的图像保存成UIImage
总共有两种方法能够把GPUImage处理过的图片转化成UIImage 方法一: UIImage *inputImage = [UIImage imageNamed:@"Lambeau ...
- Android实现弹出输入法时,顶部固定,中间部分上移的效果
前言 最近做项目时碰到一个问题,在意见反馈里面,提交按钮写到顶部,当用户输入反馈意见或者邮箱手机号时,弹出的输入法会上移整个页面,导致提交按钮显示不了. 很明显,这样的界面是非常不友好的,找了一些资料 ...
- Windows 安装Django并创建第一个应用
学习python 也有一段时间了,语法也学得差不多了,突然就想学一学python的web开源开源框架Django,我用的是Django-1.6.2.tar.gz,可以在官网https://www.dj ...
- 圣诞节来了,雪花纷飞的CSS3动画
原文链接:http://www.html5think.com/article/index/id/80
- EnterpriseArchitectect 软件的勾选的几个选项对应的中文意思
Business Process 业务流程 Requirements 需求分析 Use Case 用例 Domain Model 领域模型 Class 类 Database 数据库设计 Compone ...
- 去除android ImageView “[Accessibility] Missing contentDescription attribute on image” warning
1.在有警告的xml上选择Graphical Layout: 2.查看右上角的被涂鸦的地方,然后点击: 3.出现: 4.点击”Ignore Type“或者是“Disable Issue Type”(不 ...
- hadoop编程技巧(4)---总体情况key按类别搜索TotalOrderPartitioner
Hadoop代码测试版:Hadoop2.4 原理:携带MR该程序随机抽样提取前的输入数据,样本分类,然后,MR该过程的中间Partition此值用于当样品排序分组数据.这使得可以实现全球排名的目的. ...
- android 50 进程优先级
程序在磁盘叫程序,程序加载到内存运行起来叫进程,优先级5个级别,内存不足的时候会杀掉低级别进程. Active Process:最上面用户可以操作的. Visible Process:可见进程,部分可 ...