#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <cassert>
#include <string>
#include <ctime>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <set>
using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define rp(i,a) for(int i=head[a];i+1;i=edge[i].next)
#define cl(a,b) memset(a,b,sizeof a);
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mod 10007
const int inf = ~0u >> 2;
const ll INF = (1LL << 62) - 1;
double eps = 1e-12;
const int N = 300005 + 5;
const int M = 300005; int n, m, d; class Lct {
public:
Lct() {}
~Lct() {}
struct Node {
int value, size, add, reverse, mx;
Node *parent, *child[2];
}_nil, *node[N];
public:
void Init() {
nil = new Node;
nil->child[0] = nil->child[1] = nil;
nil->size = 0;
nil->parent = nil;
nil->mx = -(inf << 1) - 2;
nil->add = 0;
nil->value = -(inf << 1) - 2;
nil->reverse = 0;
Root = nil;
//nil->
//Insert(-(inf<<1)-2);
//Insert((inf<<1)+1);
//Insert(0);
//Insert(n + 1);
}
bool IsRoot(Node *x) {
if (x == nil)
return true;
if (x->parent->child[0] == x || x->parent->child[1] == x)
return false;
return true;
}
void update(Node *x) {
/*if (x == nil)
return;*/
x->mx = max(x->value, max(x->child[0]->mx, x->child[1]->mx));
//x->size = x->child[0]->size + x->child[1]->size + 1;
}
void down(Node *x) {
if (x == nil)return;
if (x->reverse) {
if (x->child[0] != nil) {
x->child[0]->reverse ^= 1;
}
if (x->child[1] != nil) {
x->child[1]->reverse ^= 1;
}
swap(x->child[0], x->child[1]);
x->reverse = 0;
}
if (x->add) {
if (x->child[0] != nil) {
x->child[0]->value += x->add;
x->child[0]->mx += x->add;
x->child[0]->add += x->add;
}
if (x->child[1] != nil) {
x->child[1]->value += x->add;
x->child[1]->mx += x->add;
x->child[1]->add += x->add;
}
x->add = 0;
}
}
void Rotate(Node *x, int dir) {
if (IsRoot(x))return;
Node * p = x->parent;
if (p->parent->child[0] == p)
{
p->parent->child[0] = x;
}
else if (p->parent->child[1] == p) {
p->parent->child[1] = x;
}
x->parent = p->parent;
p->child[dir ^ 1] = x->child[dir];
p->child[dir ^ 1]->parent = p;
x->child[dir] = p;
p->parent = x;
update(p);
update(x);
/*if (Root == p) {
Root = x;
}*/
}
void Splay(Node *x) {
static Node *sta[N];
int top = 0;
sta[top++] = x;
for (Node *y = x; !IsRoot(y); y = y->parent)
sta[top++] = y->parent;
while (top)down(sta[--top]);
while (!IsRoot(x)) {
if (IsRoot(x->parent)) {
if (x->parent->child[0] == x) {
Rotate(x, 1);
}
else {
Rotate(x, 0);
}
}
else if (x->parent->parent->child[0] == x->parent) {
if (x->parent->child[0] == x) {
Rotate(x->parent, 1);
Rotate(x, 1);
}
else {
Rotate(x, 0);
Rotate(x, 1);
}
}
else {
if (x->parent->child[1] == x) {
Rotate(x->parent, 0);
Rotate(x, 0);
}
else {
Rotate(x, 1);
Rotate(x, 0);
}
}
update(x);
}
}
Node *NewNode(Node *x, int val) {
x = new Node;
x->parent = nil;
x->value = val;
x->size = 1;
x->add = 0;
x->mx = val;
x->reverse = 0;
x->child[0] = x->child[1] = nil;
return x;
}
void dfs(Node *u) {
if (u->child[0] != nil)
dfs(u->child[0]);
printf(" %d", u->value);
if (u->child[1] != nil)
dfs(u->child[1]);
}
//void Insert(int u,int val){
// if (Root == nil) {
// Root = NewNode(nil, val);
// return;
// }
// Node *x=Root;
// while (x->child[val>=x->value]!=nil) {
// x = x->child[val>=x->value];
// }
// Node *t = NewNode(x,val);
// node[u] = t;
// x->child[val >= x->value] = t;
// update(x);
// Splay(t, nil);
///* printf("dfs:");
// dfs(Root);
// printf("\n");*/
//}
//void Remove(int val) {
// int rnk = FindValRank(val);
// FindRankTo(rnk - 1, nil);
// FindRankTo(rnk + 1, Root);
// Root->child[1]->child[0] = nil;
// update(Root->child[1]);
// update(Root);
//}
//int FindValRank(int val) {
// Node *x = Root;
// int sum = 0;
// while (x->child[val >= x->value]!=nil) {
// if (x->value == val)
// return sum + 1 + x->child[0]->size;
// if (val >= x->value) {
// sum += x->child[0]->size+1;
// }
// x = x->child[val >= x->value];
// }
// return sum+1+x->child[0]->size;
//}
//void FindRankTo(int rnk, Node *y) {
// Node *x = Root;
// while (x!=nil) {
// if (rnk == x->child[0]->size+1)
// {
// Splay(x, y);
// return;
// }
// if (rnk > x->child[0]->size) {
// rnk -= x->child[0]->size + 1;
// x = x->child[1];
// }
// else
// x = x->child[0];
// }
//}
//int FindRoot(int x) { //}
/*int FindRankVal(int k) {
FindRankTo(k, nil);
return Root->value;
}*/
Node *Access(Node *x) {
Node *y = x;
x = nil;
while (y != nil) {
Splay(y);
//y->child[1]->parent = y;
y->child[1] = x;
x->parent = y;
update(y);
x = y;
y = y->parent;
}
return x;
}
//Node *FindRoot(Node *x) {
// Access(x);
// Splay(x);
// while (x->child[0] != nil)x = x->child[0];
// Splay(x);
// return x;
//}
void Cut(Node *x) {
//ChangeRoot(x->parent);
/*Access(x);
Splay(x);
x->reverse ^= 1;*/
ChangeRoot(x);
x->child[0]->parent = nil;
x->child[0] = nil;
update(x);
}
void Link(Node *x, Node *y) {
//printf("%d %d#\n", x->value, y->value);
/*Access(x);
Splay(x);
x->reverse ^= 1;*/
ChangeRoot(x);
x->parent = y;
//Access(x);
//
}
void ChangeRoot(Node *x) {
Access(x);
Splay(x);
x->reverse ^= 1;
}
void AddVal(Node *x, Node *y, int val) {
ChangeRoot(y);
ChangeRoot(x);
//Node *u = Access(x);
//Node *u = BecomeRoot(x);
/*Cut(y->child[1]);
while (y->child[0] != x)y = y->child[0];
Cut(x->child[0]);*/
//Access(x);
x->value += val;
x->add += val;
x->mx += val;
}
int QueryMaxVal(Node *x, Node *y) {
ChangeRoot(y);
ChangeRoot(x);
//Node *u = Access(x);
//BecomeRoot(x);
return x->mx;
/*Cut(y->child[1]);
while(y->child[0])*/
}
bool IsSameTree(Node *u, Node *v) {
while (u->parent != nil)u = u->parent;
while (v->parent != nil)v = v->parent;
return u == v;
}
public:
int w[N];
Node *Root, *nil;
};
struct Seg {
int l, r, k, index;
bool operator < (const Seg & rhs)const {
return r < rhs.r;
}
}seg[M];
Lct lct;
//SplayTree spt;
int ans[M];
void printErr() {
printf("-1\n");
}
int nd1[N], nd2[N];
int main() {
int n;
while (scanf("%d",&n)!=-1) {
lct.Init();
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
//g[u].push_back(v);
nd1[i] = u;
nd2[i] = v;
}
for (int i = 1; i <= n; i++) {
scanf("%d", &lct.w[i]);
lct.node[i] = lct.NewNode(lct.node[i], lct.w[i]);
}
for (int i = 1; i < n; i++)
lct.Link(lct.node[nd1[i]], lct.node[nd2[i]]);
/*for (int i = 1; i <= n; i++)
for (int j = 0; j < g[i].size(); j++)
lct.Link(lct.node[i], lct.node[g[i][j]]);*/
//for (int i = 1; i <= n; i++) {
// if (lct.IsRoot(lct.node[i])) {
// printf("Root :%d", i);
// lct.dfs(lct.node[i]);
// printf("\n");
// }
//}
scanf("%d", &m);
while (m--) {
int op;
scanf("%d", &op);
if (op == 1) {
int x, y;
scanf("%d%d", &x, &y);
if (lct.IsSameTree(lct.node[x], lct.node[y])) {
printErr();
continue;
}
lct.Link(lct.node[x], lct.node[y]);
}
if (op == 2) {
int x, y;
scanf("%d%d", &x, &y);
if (x==y||!lct.IsSameTree(lct.node[x], lct.node[y])) {
printErr();
continue;
}
lct.ChangeRoot(lct.node[x]);
lct.Cut(lct.node[y]);
}
if (op == 3) {
int w, x, y;
scanf("%d%d%d", &w, &x, &y);
if (!lct.IsSameTree(lct.node[x], lct.node[y])) {
printErr();
continue;
}
lct.AddVal(lct.node[x], lct.node[y], w);
}
if (op == 4) {
int x, y;
scanf("%d%d", &x, &y);
if (!lct.IsSameTree(lct.node[x], lct.node[y])) {
printErr();
continue;
}
printf("%d\n", lct.QueryMaxVal(lct.node[x], lct.node[y]));
}
}
printf("\n");
}
return 0;
}

hdu 4010 Lct动态链接树的更多相关文章

  1. Lct 动态链接树

    通过树链剖分能了解轻重边 Acdreamer 的博客 http://blog.csdn.net/acdreamers/article/details/10591443 然后看杨哲大大的论文,能了解轻重 ...

  2. Hdu 2475-Box LCT,动态树

    Box Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  3. BZOJ 3510 - 首都 「 $LCT$ 动态维护树的重心」

    这题 FlashHu 的优化思路值得借鉴 前置引理 树中所有点到某个点的距离和中,到重心的距离和是最小的. 把两棵树通过某一点相连得到一颗新的树,新的树的重心必然在连接原来两棵树重心的路径上. 一棵树 ...

  4. 【BZOJ4025】二分图(LCT动态维护图连通性)

    点此看题面 大致题意: 给你一张图以及每条边的出现时间和消失时间,让你求每个时间段这张图是否是二分图. 二分图性质 二分图有一个比较简单的性质,即二分图中不存在奇环. 于是题目就变成了:让你求每个时间 ...

  5. HDU 5862 Counting Intersections(离散化+树状数组)

    HDU 5862 Counting Intersections(离散化+树状数组) 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 D ...

  6. LuoguP2617 Dynamic Rankings (动态主席树学习理解)

    题目地址 题目链接 题解 动态主席树的板子题.动态主席树其实和静态的有很大差别,虽然同样是n个根,但是节点并不能共用,每个根节点表示bit上的一段区间. 所以其实是个树套树的东西来着,外层是bit,内 ...

  7. HDU1199 动态线段树 // 离散化

    附动态线段树AC代码 http://acm.hdu.edu.cn/showproblem.php?pid=1199 因为昨天做了一道动态线段树的缘故,今天遇到了这题没有限制范围的题就自然而然想到了动态 ...

  8. HDU5367 思维map // 动态线段树

    地主毛毛有n座山,这些山在地主家门前排成一条直线.这些山一开始均有相同的高度.  每一天,毛毛都会要求花花开挖机把几座山挖掉一定高度,或者给一些山堆上一些高度.并且要求花花报告现在有多少座山属于“高山 ...

  9. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

随机推荐

  1. Dropwizard+jersey+MDC实现日志跟踪以及接口响应时间统计

    一.实现接口响应时间统计 1.1添加全局请求过滤器并注册 import org.apache.log4j.MDC; import org.slf4j.Logger; import org.slf4j. ...

  2. NTFS 文件系统结构

    背景 NTFS 作为一个新的文件系统,因其安全性高而受到越来越多的重视,越来越多的应用采用了NTFS 文件系统.作为一个新的文件系统,NTFS 有着许多区别于FAT32 的优点,如磁盘配额.文件系统加 ...

  3. Pytorch_第七篇_深度学习 (DeepLearning) 基础 [3]---梯度下降

    深度学习 (DeepLearning) 基础 [3]---梯度下降法 Introduce 在上一篇"深度学习 (DeepLearning) 基础 [2]---神经网络常用的损失函数" ...

  4. Prometheus监控神器-Rules篇

    本章主要对如何使用Prometheus与Alertmanager组件集成配置,以及对警报规则 Rules 的俩种类型及其模板内容进行讲解. 与Alertmanager集成 Prometheus把产生的 ...

  5. Could not update Activiti database schema: unknown version from database: '5.22.x.x'

    原因:activiti 相关的jar版本和表 act_ge_property 中 schema.version 所存储的版本不一致导致报错的. 查看activiti 相关jar版本 然后修改表中的版本 ...

  6. Nginx定时日志切割

    Nginx定时日志切割 现有的日志都会存在access.log文件中,但是随着时间的推移,这个文件的内容会越来越多,体积会越来越大,不便于运维 人员查看,所以我们可以通过把这个大的日志文件切割为多份不 ...

  7. CSDN新版Markdown编辑器(Alpha 2.0版)

    Markdown编辑器 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建 ...

  8. C#LeetCode刷题之#824-山羊拉丁文​​​​​​​(Goat Latin)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3971 访问. 给定一个由空格分割单词的句子 S.每个单词只包含大 ...

  9. 攻防世界-web(进阶)-NewsCenter

    打开文件发现有个搜索框,考虑是XSS或SQL注入,输入弹框语句不显示考虑到SQL注入,抓包将抓包信息保存为txt,用sqlmap爆破. 输入:sqlmap -r “sql.txt”,输出如下数据库版本 ...

  10. 存储系列之 从ext2到ext3、ext4 的变化与区别

    引言:ext3 和 ext4 对 ext2 进行了增强,但是其核心设计并没有发生变化.所以建议先查看上上篇的<存储系列之 Linux ext2 概述 >,有了ext2的基础,看这篇就是so ...