HDU 5002 Tree
题意:
一棵树 支持删边加边、路径权值加值、路径权值改值、路径求第二大的数字和其个数
思路:
LCT的第二题 题意已经把功能都告诉了 比較裸
要注意的是权值加值和改值两个操作的标记下放问题 要先down改值 再down加值
对于路径的操作通过mroot变换树的形态再access拿出路径比較方便 不要像我上一篇一样搞lca
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
#define N 100010
#define L(x) (ch[x][0])
#define R(x) (ch[x][1])
#define inf -2147483640 int ch[N][2], pre[N], rev[N], me[N];
int cov[N], add[N], size[N], max1[N], num1[N], max2[N], num2[N];
bool rt[N]; struct helper {
int val, num;
bool operator<(const helper ff) const {
return val > ff.val;
}
} hel[10]; void Update_COV(int u, int d) {
if (!u)
return;
me[u] = d;
cov[u] = d;
add[u] = inf;
max1[u] = d;
num1[u] = size[u];
max2[u] = inf;
num2[u] = 0;
} void Update_Add(int u, int d) {
if (!u)
return;
me[u] += d;
if (add[u] != inf)
add[u] += d;
else
add[u] = d;
max1[u] += d;
if (max2[u] != inf)
max2[u] += d;
} void Update_Rev(int u) {
if (!u)
return;
swap(L(u), R(u));
rev[u] ^= 1;
} void down(int u) {
if (rev[u]) {
Update_Rev(L(u));
Update_Rev(R(u));
rev[u] = 0;
}
if (cov[u] != inf) {
Update_COV(L(u), cov[u]);
Update_COV(R(u), cov[u]);
cov[u] = inf;
}
if (add[u] != inf) {
Update_Add(L(u), add[u]);
Update_Add(R(u), add[u]);
add[u] = inf;
}
} void up(int u) {
size[u] = size[L(u)] + size[R(u)] + 1;
hel[0].val = max1[L(u)];
hel[0].num = num1[L(u)];
hel[1].val = max2[L(u)];
hel[1].num = num2[L(u)];
hel[2].val = max1[R(u)];
hel[2].num = num1[R(u)];
hel[3].val = max2[R(u)];
hel[3].num = num2[R(u)];
hel[4].val = me[u];
hel[4].num = 1;
sort(hel, hel + 5);
int i;
for (i = 1; i < 5; i++) {
if (hel[i].val != hel[i - 1].val)
break;
}
max1[u] = hel[0].val;
max2[u] = hel[i].val;
num1[u] = num2[u] = 0;
for (i = 0; i < 5; i++) {
if (hel[i].val == max1[u])
num1[u] += hel[i].num;
else if (hel[i].val == max2[u])
num2[u] += hel[i].num;
}
} //Rotate P Splay 一般不变
void Rotate(int x) {
int y = pre[x], kind = ch[y][1] == x;
ch[y][kind] = ch[x][!kind];
pre[ch[y][kind]] = y;
pre[x] = pre[y];
pre[y] = x;
ch[x][!kind] = y;
if (rt[y])
rt[y] = false, rt[x] = true;
else
ch[pre[x]][ch[pre[x]][1] == y] = x;
up(y);
} //P函数先将splay根结点到u的路径上全部的结点的标记逐级下放
void P(int u) {
if (!rt[u])
P(pre[u]);
down(u);
} void Splay(int u) {
P(u);
while (!rt[u]) {
int fa = pre[u], ffa = pre[fa];
if (rt[fa])
Rotate(u);
else if ((R(ffa) == fa) == (R(fa) == u))
Rotate(fa), Rotate(u);
else
Rotate(u), Rotate(u);
}
up(u);
} //将root到u的路径变成实边
int Access(int u) {
int v = 0;
for (; u; u = pre[v = u]) {
Splay(u);
rt[R(u)] = true, rt[R(u) = v] = false;
up(u);
}
return v;
} //使u成为它所在的树的根
void mroot(int u) {
Access(u);
Splay(u);
Update_Rev(u);
} //连接两棵树 u接在v上
void link(int u, int v) {
mroot(u);
pre[u] = v;
} //u-v边断开
void cut(int u, int v) {
mroot(u);
Access(u);
Splay(v);
pre[L(v)] = pre[v];
pre[v] = 0;
rt[L(v)] = true;
L(v) = 0;
up(v);
} //u-v路径权值变为w
void COV(int u, int v, int w) {
mroot(u);
Access(v);
Splay(v);
Update_COV(v, w);
} //u-v路径+w
void ADD(int u, int v, int w) {
mroot(u);
Access(v);
Splay(v);
Update_Add(v, w);
} //u-v路径最大值
void query(int u, int v) {
mroot(u);
Access(v);
Splay(v);
if (max2[v] != inf)
printf("%d %d\n", max2[v], num2[v]);
else
printf("ALL SAME\n");
} struct edge {
int v, next;
} ed[N * 2];
int head[N], tot; void addedge(int u, int v) {
ed[tot].v = v;
ed[tot].next = head[u];
head[u] = tot++;
} //利用dfs初始化pre数组 建立LCT
void dfs(int u) {
for (int i = head[u]; ~i; i = ed[i].next) {
int v = ed[i].v;
if (pre[v] != 0)
continue;
pre[v] = u;
dfs(v);
}
} int main() {
int T, t, n, m, i, op, u, v, x, y, w;
max1[0] = max2[0] = inf;
rt[0] = true;
scanf("%d", &T);
for (t = 1; t <= T; t++) {
scanf("%d%d", &n, &m);
for (i = 1; i <= n; i++) {
scanf("%d", &me[i]);
max1[i] = me[i];
max2[i] = inf;
num1[i] = 1;
num2[i] = 0;
size[i] = 1;
add[i] = cov[i] = inf;
L(i) = R(i) = pre[i] = rev[i] = 0;
rt[i] = true;
}
tot = 0;
memset(head, -1, sizeof(head));
for (i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
pre[1] = -1;
dfs(1);
pre[1] = 0;
printf("Case #%d:\n", t);
while (m--) {
scanf("%d", &op);
if (op == 1) {
scanf("%d%d%d%d", &u, &v, &x, &y);
cut(u, v);
link(x, y);
} else if (op == 2) {
scanf("%d%d%d", &u, &v, &w);
COV(u, v, w);
} else if (op == 3) {
scanf("%d%d%d", &u, &v, &w);
ADD(u, v, w);
} else {
scanf("%d%d", &u, &v);
query(u, v);
}
}
}
return 0;
}
HDU 5002 Tree的更多相关文章
- HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...
- HDU 5002 Tree LCT 区间更新
Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action?c ...
- hdu 5002 (动态树lct)
Tree Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- hdu 5909 Tree Cutting [树形DP fwt]
hdu 5909 Tree Cutting 题意:一颗无根树,每个点有权值,连通子树的权值为异或和,求异或和为[0,m)的方案数 \(f[i][j]\)表示子树i中经过i的连通子树异或和为j的方案数 ...
- HDU 5044 Tree(树链剖分)
HDU 5044 Tree field=problem&key=2014+ACM%2FICPC+Asia+Regional+Shanghai+Online&source=1&s ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)
Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Total Su ...
- HDU 4757 Tree 可持久化字典树
Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4757 Des ...
- HDU 6228 - Tree - [DFS]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6228 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
随机推荐
- 轻松学习之Linux教程六 正則表達式具体解释
本系列文章由@超人爱因斯坦出品.转载请注明出处. 作者:超人爱因斯坦 个人站点:http://www.hpw123.net 文章链接:http://hpw123.net/a/L ...
- 纯CSS实现各类气球泡泡对话框效果
原文 纯CSS实现各类气球泡泡对话框效果 一.关于纯CSS实现气泡对话框 首先,来张大图: 上边这张黄黄的,大大的,圆圆的,有个小尾巴,文字内容有些YY的图片,就是使用纯CSS实现的气泡对话框效果,一 ...
- hdu3886(数位dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3886 题意:给一定区间[A,B],一串由/,\,-组成的符号串.求满足符号串的数字个数. •/表示数字 ...
- 自己定义 ViewGroup 支持无限循环翻页之三(响应回调事件)
大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处,再次感谢 ################################ ...
- 设置 zend studio 默认编码为UTF8
今天用zend studio 打开文件时发现为乱码,这肯定是编码出了问题,我看了一下果然是编码出了问题,默认的是以GBK编码方式打开,我换utf8编码打开就好了,换编码打开的方法是: 1点击工具栏中的 ...
- hdu4670(树上点分治+状态压缩)
树上路径的f(u,v)=路径上所有点的乘积. 树上每个点的权值都是由给定的k个素数组合而成的,如果f(u,v)是立方数,那么就说明f(u,v)是可行的方案. 问有多少种可行的方案. f(u,v)可是用 ...
- WPF换肤之二:可拉动的窗体
原文:WPF换肤之二:可拉动的窗体 让我们接着上一章: WPF换肤之一:创建圆角窗体 来继续. 在这一章,我主要是实现对圆角窗体的拖动,改变大小功能. 拖动自绘窗体的步骤 首先,通过上节的设计,我们知 ...
- Nim博弈游戏
给定n堆石子,每次每人能从一堆石子中取若干个石子(不能不取),最后不能取石子者败 对于这个游戏,我们要判断的是,给定局势下,先手者胜还是败 设先手胜的局势为N-postion,先手败的局势为P-pos ...
- github源码开源区块链浏览器
<ignore_js_op> 帅爆了吧 https://blockexplorer.com/ github源码:https://github.com/bitcoin-blockexplor ...
- centos 64位编译安装 glibc-2.14
cd /opt wget http://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.gz tar -xzf glibc-2.14.tar.gz cd glibc-2.14 ...