题目

Link

分析

典型的树链剖分题,

树链剖分学习资料

Code

#include <bits/stdc++.h>

using namespace std;

const int maxn = 30000 + 131;
struct Edge {
int Next;
int To;
}edge[maxn<<1];
int Head[maxn], tot, n;
///以下是重链数据定义
int top[maxn]; //重链的顶点
int deep[maxn]; //树上节点的深度
int Pre[maxn]; //父节点
int size[maxn]; //子树节点大小
int son[maxn]; //重链中节点的子节点
///以下有关离散到线段树数据定义
int t_s[maxn]; //树上的点离散到线段树
int s_t[maxn]; //线段树映射回树上的点。
int pos;
//题目数据
int w[maxn]; void INIT() {
tot = pos = 0;
memset(son, -1, sizeof(son));
memset(Head,-1, sizeof(Head));
}
////
void Addedge(int from, int to) {
edge[tot].To = to;
edge[tot].Next = Head[from];
Head[from] = tot++;
} void Getlist(int root, int pre, int d) { //获得重链
deep[root] = d;
Pre[root] = pre;
size[root] = 1;
for(int i = Head[root]; ~i; i = edge[i].Next) {
int v = edge[i].To;
if(v != pre) {
Getlist(v, root, d+1);
size[root] += size[v]; //累加size
if(son[root] == -1 || size[son[root]] < size[v])
son[root] = v; //更新重链子节点
}
}
}
////离散点到线段树上
void Lisan_TtoS(int u, int root) {
top[u] = root;
t_s[u] = ++pos;
s_t[t_s[u]] = u;
if(son[u] == -1) return ;
Lisan_TtoS(son[u], root); for(int i = Head[u]; ~i; i = edge[i].Next) {
int v = edge[i].To;
if(v != son[u] && v != Pre[u])
Lisan_TtoS(v,v); //新的重链开始.
}
}
////线段树
int Sum[maxn << 2];
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1 void PushUp(int rt) {
Sum[rt] = Sum[rt<<1] + Sum[rt<<1|1];
} void Build(int l, int r, int rt) {
if(l == r) {
Sum[rt] = w[s_t[l]];
/*cout << "This is tree idx:" << s_t[l] \
<< " values:" << w[s_t[l]] << endl;*/
return ;
}
int m = (l + r) >> 1;
Build(lson);
Build(rson);
PushUp(rt);
} void Update(int pos, int val, int l, int r, int rt) {
if(l == r) {
Sum[rt] = val;
//cout << "This is the tree id: " << s_t[l] << endl;
return ;
}
int m = (l + r) >> 1;
if(pos <= m) Update(pos, val, lson);
else Update(pos, val, rson);
PushUp(rt);
} int Query(int L, int R, int l, int r, int rt) {
//cout << "seg l : " << l << " r : " << r ;
//cout << " Find L:" << L << " R: " << R << endl;
if(L <= l && r <= R) {
//cout << "Had add : " << Sum[rt] << endl;
return Sum[rt];
}
int m = (l + r) >> 1;
int ret = 0;
if(L <= m) ret += Query(L, R, lson);
if(R > m) ret += Query(L, R, rson);
return ret;
}
////查询(u,v)
int Find(int u, int v) { /// u to v
int fa_u = top[u]; /// u总是更深的点.
int fa_v = top[v];
int ret = 0;
while(fa_u != fa_v) {
if(deep[fa_u] < deep[fa_v]) {
swap(u, v);
swap(fa_v,fa_u);
}
//cout << "This is the list :" << fa_u << "->" << u << endl;
//cout << "This is the Segm :" << t_s[fa_u] << "->" << t_s[u] << endl;
ret += Query(t_s[fa_u], t_s[u], 1, n, 1);
u = Pre[fa_u];
fa_u = top[u];
}
// 点, 所以会有两点重合的情况。
// 边的处理, 可以理解 i 点 to j 点的边 v 就是 j 点的权值
// root 处理为最小只即可 or (0) or 各种适合值。
if(deep[u] > deep[v]) swap(u, v);
ret += Query(t_s[u], t_s[v], 1, n, 1);
return ret;
} int main() {
int T;
scanf("%d",&T);
for(int kase = 1; kase <= T; ++kase) {
scanf("%d",&n);
INIT();
for(int i = 1; i <= n; ++i)
scanf("%d",w+i);
int u, v;
for(int i = 1; i < n; ++i) {
scanf("%d%d",&u, &v);
u++, v++;
Addedge(u, v);
Addedge(v, u);
}
Getlist(1, -1, 0);
Lisan_TtoS(1,1);
Build(1, n, 1);
printf("Case %d:\n",kase);
int q;
scanf("%d",&q);
for(int i = 0; i < q; ++i) {
int op;
scanf("%d%d%d",&op,&u,&v);
if(op == 1) {
Update(t_s[++u], v, 1, n, 1);
}
else {
u++, v++;
printf("%d\n", Find(u, v));
}
}
}
return 0;
}

LightOJ 1348 (树链剖分 + 线段树(树状数组))的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

随机推荐

  1. jQuery 与 Ajax 的应用

    Ajax 全称为 "Asynchronous JavaScript and XML"(异步 JavaScript 和 XML ),它并不是指一种单一的技术,而是有机地利用了一系列交 ...

  2. react 事件绑定 es5/es6

    // vscode shift + ctrl + v 预览 es 5 写法 无参函数的绑定 first methods 定义函数: handleClick(e) { // e - 事件对象 e.pre ...

  3. Frame Interpolation

    对于视频网站.电视厂商以及进行视频压制的用户来说,改变视频的帧率算是一个比较常见的需求.视频网站改变帧率主要是为了向不同级别的网站用户提供差异化服务:电视厂商则是以提供更好的显示效果作为电视的卖点:对 ...

  4. Stars project

    说明:收藏一些比较好的开源项目 Python实现了所有的排序算法 Github:https://github.com/TheAlgorithms/Python 该项目用Python实现了所有的排序算法 ...

  5. P1162 填涂颜色

    原题链接 https://www.luogu.org/problemnew/show/P1162 一道很水很简单的搜索题,好吧我还是交了4次才过的...... 说一下简单的思路: 首先输入n*n的矩阵 ...

  6. k8s常用命令演示

    kubectl run --image=xxx name_xx --port kubectl run --image=nginx nginx-app --port=80 kubectl expose ...

  7. Redis 高级部分

    一.主从复制   image.png Rdis 的主从复制特点   image.png 1. 配置主从 实现方式同样有两种: 命令方式和配置文件方式 命令方式 只需要在从服务器上执行如下命令即可 sl ...

  8. Redis-Cluster操作命令大全

    今天整理下redis-cluster操作命令 一.Cluster操作命令 CLUSTER INFO 打印集群的信息 CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相 ...

  9. js javascript 简易随机值穿插加解密【原】

    适用场景 本方法适用于需要对敏感信息进行加密传输,但加解密要求又不高的场景,因为是前台的javascript加解密,所以其实还是能通过js代码分析出原始值来的. 如果您对信息极其敏感, 比例登录密码这 ...

  10. linux下的/dev/shm/ 以及与swap目录的区别【转】

    /dev/shm 概念 首先可以看出来/dev/shm是一个设备文件, 可以把/dev/shm看作是系统内存的入口, 可以把它看做是一块物理存储设备,一个tmp filesystem, 你可以通过这个 ...