【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文件导入到你的数据库中,以下所有操作都是基于该数据库表操作的!!! [此笔记是本人看着视频加上自 ...
随机推荐
- ExecuteScalar的学习日志
一:今天写关于调用sqlhelper类的时候出现了一个异常,我仔细观察没有错误啊,怎么回事:看图 二:出现错误时id的结果是0,也就是说ExcuteScalar的结果是null,明明数据库里有多行数据 ...
- eclipse常见错误
1.The superclass “javax.servlet.http.httpservlet” is not found in the build path 原因:未添加server librar ...
- Linux的IP设置参考
位置:etc/network/interfaces 内容: 第一段是网口1自动从DHCP处获得IP 第二段是网口2静态分配IP 如果是IPv6,请把 iface eth0 inet dhcp(stat ...
- apache php gzip压缩输出的实现方法
一.gzip介绍 gzip是GNU zip的缩写,它是一个GNU自由软件的文件压缩程序,也经常用来表示gzip这种文件格式.软件的作者是Jean-loup Gailly和Mark Adler.1992 ...
- 2013=7=12 ACM培训第一天
ACM培训第一天,尽管我嘴上说是来打酱油的,但我非常想学好.1.一定要多思考,多总结:2.多问同学 :3.学会向女生说话,大胆,自信.(今天有女生向我说话了,很高兴.她很大胆,我要向她学习...... ...
- poj 2479 Maximum sum (最大字段和的变形)
题目链接:http://poj.org/problem?id=2479 #include<cstdio> #include<cstring> #include<iostr ...
- 短随机唯一id生成参考
<?php function getRandOnlyId() { //新时间截定义,基于世界未日2012-12-21的时间戳. $endtime=1356019200;//2012-12-21时 ...
- Installing scikit-learn
Installing scikit-learn http://scikit-learn.org/stable/install.html Installing scikit-learn There ar ...
- How to install Python 2.7 and Python 3.3 on CentOS 6
原文地址:http://toomuchdata.com/2014/02/16/how-to-install-python-on-centos/
- 多次读取请求request里数据
如果请求是GET方法,可以直接通过getParameter(String param)方法读取指定参数,可读取多次: 而POST方法的参数是存储在输入流中,只能读一次,不能多次读取. 有时需要在fil ...