题目

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. WebApi(五)-Swagger接口文档①简单集成

    1,通过NuGet引用Swashbuckle 2,打开项目属性-->生成,勾选XML文档文件,保存 3,找到项目App_Start文件夹下WebApiConfig查找GetXmlComments ...

  2. 一个解释volatile关键字最好的例子

    小例子 public class VolatileTest { private static volatile int INIT_VALUE = 0; private final static int ...

  3. ubuntu下python跑任务输出到文件中遇到的一些问题(输出重定向)

    之前主要是参考https://www.cnblogs.com/chason95/articles/9760291.html 一般使用 python test.py > ./log.txt 或 p ...

  4. DP的优化总结

    一.预备知识 \(tD/eD\) 问题:状态 t 维,决策 e 维.时间复杂度\(O(n^{e+t})\). 四边形不等式: 称代价函数 w 满足凸四边形不等式,当:\(w(a,c)+w(b,d)\l ...

  5. Mysql 查询当月时间数据

    SELECTDATE_FORMAT(CURDATE(), '%Y%m'), DATE_FORMAT(t.transactiontime, '%Y%m'),t.*FROM ttransactions t ...

  6. JS学习笔记Day22

    一.Ajax的概念 (一)Ajax是一种在无需重新加载整个网页(刷新网页)的情况下能够更新部分网页的技术 (二)Ajax的全称是Asynchronous JavaScript and XML,即异步J ...

  7. C# activex开发中 axwebbrowser控件及 IE浏览器设置

    <object type='application/x-vlc-plugin' id='vlc' events='True' codebase='../cab/axvlc.cab' classi ...

  8. [源码分析]Java1.8中StringJoiner的使用以及源码分析

    [源码分析]StringJoiner的使用以及源码分析 StringJoiner是Java里1.8新增的类, 或许有一部分人没有接触过. 所以本文将从使用例子入手, 分析StringJoiner的源码 ...

  9. DirectX11--实现一个3D魔方(2)

    前言 上一章我们主要讲述了魔方的构造和初始化.纹理的准备工作.目前我还没有打算讲Direct3D 11关于底层绘图的实现,因此接下来这一章的重点是魔方的旋转.因为我们要的是能玩的魔方游戏,而不是一个观 ...

  10. Maven之阿里云镜像仓库配置

    方式一:全局配置:修改maven的setting.xml配置 在mirrors节点下面添加子节点: <mirror> <id>nexus-aliyun</id> & ...