LightOJ 1348 (树链剖分 + 线段树(树状数组))
题目
分析
典型的树链剖分题,
树链剖分学习资料
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 (树链剖分 + 线段树(树状数组))的更多相关文章
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- 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 ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
随机推荐
- Linux之判断字符串是否为空
help命令可以查看帮助 help test 正确做法: #!/bin/sh STRING= if [ -z "$STRING" ]; then echo "ST ...
- 你懂redis吗
一.redis简介 Redis是当前比较热门的NOSQL系统之一,它是一个开源的使用ANSI c语言编写的key-value存储系统(区别于MySQL的二维表格的形式存储.).和Memcache类似, ...
- C# 使用CsvHelper读取.csv文件
1,先到包管理器下载 安装CsvHelper. 2,创建一个与csv文件字段名称相同的类 public class SurveyInfoModel { public string DIST_CD { ...
- react-native-echarts在打包时出现的坑
react-native-echarts目前是RN开发中使用echarts图表最好的插件了,用法与Echarts完全一致,默认提供了三个属性: option (object): The option ...
- python的局部变量,全局变量,类变量,实例变量
定义: a.全局变量:在模块内.在所有函数外面.在class外面,这就是全局变量. b.局部变量:在函数内.在class的方法内(未加self修饰的),这就是局部变量. c. 静态变量:在class内 ...
- JQ高级
一.选择器 css语法选择器 $('css3 选择器位‘) 索引匹配 $('div:eq(0)') $('div').eq(0) 内容 $('div:contains(标签文本内容)') // 注:采 ...
- 「Algospot」量化QUANTIZE
一道不难的DP题,主要是为了总结这类最优化题的思路:同时还学到了一个新操作 传送门:$>here<$ 题意 给出一个长度为$N$的序列,要求最多使用s个数字进行量化(有损压缩),即代替原数 ...
- docker上传自己的镜像
https://blog.csdn.net/boonya/article/details/74906927 需要注意的就是命名规范 docker push 注册用户名/镜像名
- 使用apidoc生成项目文档
[1]npm install apidoc -g 全局安装apidoc [2]apidoc -v 查看是否安装成功 [3]apidoc.json apidoc的项目级配置文件,它必须位于整个工程目录顶 ...
- python并发编程之多线程基础知识点
1.线程理论知识 概念:指的是一条流水线的工作过程的总称,是一个抽象的概念,是CPU基本执行单位. 进程和线程之间的区别: 1. 进程仅仅是一个资源单位,其中包含程序运行所需的资源,而线程就相当于车间 ...