POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权
题意: 知道了一颗有 n 个节点的树和树上每条边的权值,对应两种操作:
0 x 输出 当前节点到 x节点的最短距离,并移动到 x 节点位置
1 x val 把第 x 条边的权值改为 val
题意: 知道了一颗有 n 个节点的树和树上每条边的权值,对应两种操作:
0 x 输出 当前节点到 x节点的最短距离,并移动到 x 节点位置
1 x val 把第 x 条边的权值改为 val
LCA +RMQ+树状数组
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <algorithm>
- using namespace std;
- const int maxn = 2e5+;
- int N,Q,S;
- //vector <int> G[maxn];
- struct edge{
- int to,next,w;
- }e[*maxn];
- int head[*maxn],tot;
- void add_edge(int u,int v,int w)
- {
- e[tot].to = v;
- e[tot].w = w;
- e[tot].next = head[u];
- head[u] = tot++;
- e[tot].to = u;
- e[tot].w = w;
- e[tot].next = head[v];
- head[v] = tot++;
- }
- int in[maxn],out[maxn],P[*maxn],fa[maxn][],dep[maxn],dis[maxn],cnt;
- void dfs(int u,int _fa,int _dep,int _dis)
- {
- in[u] = ++cnt;
- P[cnt] = u;
- fa[u][] = _fa;
- dis[u] = _dis;
- dep[u] = _dep;
- for(int i=head[u];~i;i=e[i].next)
- {
- int v = e[i].to;
- if(v == _fa) continue;
- dfs(v,u,_dep+,_dis+e[i].w);
- }
- out[u] = ++cnt;
- }
- void debug()
- {
- printf("in:\t");for(int i=;i<=N;i++) printf("%d ",in[i]);puts("");
- printf("out:\t");for(int i=;i<=N;i++) printf("%d ",out[i]);puts("");
- printf("p:\t");for(int i=;i<=cnt;i++) printf("%d ",P[i]);puts("");
- printf("dis:\t");for(int i=;i<=N;i++) printf("%d ",dis[i]);puts("");
- printf("dep:\t");for(int i=;i<=N;i++) printf("%d ",dep[i]);puts("");
- printf("edge:");for(int i=;i<tot;i++) printf("\tto:%d w:%d\n",e[i].to,e[i].w);
- }
- int initLCA()
- {
- int m = (int)log(N)/log()+;
- for(int k=;k<m;k++)
- {
- for(int v=;v<=N;v++)
- {
- if(fa[v][k] < ) {fa[v][k+] = -;continue;}
- else fa[v][k+] = fa[fa[v][k]][k];
- }
- }
- }
- int LCA(int u,int v)
- {
- int m = (int)log(N)/log()+;
- if(dep[v] > dep[u]) swap(u,v);
- for(int k=;k<m;k++)
- {
- if((dep[u]-dep[v])>>k & )
- u = fa[u][k];
- }
- if(u == v) return u;
- for(int k=m-;k>=;k--)
- {
- if(fa[u][k] != fa[v][k])
- {
- u = fa[u][k];
- v = fa[v][k];
- }
- }
- return fa[u][];
- }
- int c[*maxn];
- int lowbit(int x) {return x&-x;}
- void init()
- {
- memset(head,-,sizeof head);
- memset(fa,-,sizeof fa);
- memset(c,,sizeof c);
- memset(in,,sizeof in);
- memset(out,,sizeof out);
- tot = ;
- cnt = ;
- }
- void add(int x,int d)
- {
- while(x)
- {
- c[x] += d;
- x -= lowbit(x);
- }
- }
- void add_seg(int l,int r,int d)
- {
- add(r,d);
- add(l-,-d);
- }
- int sum(int x)
- {
- int res = ;
- //printf("u:%d ",P[x]);
- while(x <= cnt)
- {
- res += c[x];
- x += lowbit(x);
- }
- //printf("res:%d\n",res);
- return res;
- }
- int dist(int x)
- {
- if(x == -) return ;
- return sum(in[x]) + dis[x];
- }
- int main()
- {
- //freopen("input.txt","r",stdin);
- while(~scanf("%d%d%d",&N,&Q,&S))
- {
- init();
- for(int i=,u,v,w;i<N-;i++)
- {
- scanf("%d%d%d",&u,&v,&w);
- add_edge(u,v,w);
- }
- dfs(,-,,);
- //debug();
- initLCA();
- for(int i=;i<tot;i+=)
- {
- if(dep[e[i].to] < dep[e[i+].to]) swap(e[i].to,e[i+].to);
- }
- int op;
- for(int i=,a,b,c;i<Q;i++)
- {
- scanf("%d",&op);
- if(op == )
- {
- scanf("%d",&a);
- int lca = LCA(S,a);
- //printf("lca:%d\n",lca);
- printf("%d\n",dist(S)+dist(a)-*(dist(lca)));
- S = a;
- }else
- {
- scanf("%d%d",&a,&b);
- a--;
- int u = e[a*].to;
- int dw = b - (dist(u) - dist(fa[u][]));
- //printf("dw:%d u:%d\n",dw,u);
- add_seg(in[u],out[u],dw);
- }
- }
- }
- }
树链部分
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #define lson l, m, rt << 1
- #define rson m + 1, r, rt << 1 | 1
- using namespace std;
- typedef long long ll;
- const int MAXN = 2e5 + ;
- int n, q, s;
- int fa[MAXN]; // fa[v]: v 的父亲
- int dep[MAXN]; // dep[v]: v 的深度(根深度为1)
- int siz[MAXN]; // : 以 v 为根的子树的节点数
- int son[MAXN]; // : 重儿子,siz[u] 为 v 的子节点中 siz 值最大的,那么 u 就是 v 的重儿子
- int top[MAXN]; // : 表示 v 所在的重链的顶端节点
- int w[MAXN]; // : 表示 v 与其父亲节点的连边在线段树中的位置
- int num; // 将树映射到线段树上的标号
- int cnt, head[MAXN];
- struct Edge {
- int to, next;
- }edge[MAXN];
- struct E {
- int u, v, c;
- }e[MAXN];
- void addedge(int u, int v) {
- edge[cnt].to = v;
- edge[cnt].next = head[u];
- head[u] = cnt++;
- }
- void dfs(int u) {
- siz[u] = ; son[u] = ;
- for(int i = head[u]; ~i; i = edge[i].next) {
- if(edge[i].to != fa[u]) {
- fa[edge[i].to] = u;
- dep[edge[i].to] = dep[u] + ;
- dfs(edge[i].to);
- if(siz[edge[i].to] > siz[son[u]]) son[u] = edge[i].to;
- siz[u] += siz[edge[i].to];
- }
- }
- }
- void build_tree(int u, int tp) {
- w[u] = ++num; top[u] = tp;
- if(son[u]) build_tree(son[u], top[u]); // 使重链各边在线段树中呈连续分布
- for(int i = head[u]; ~i; i = edge[i].next) {
- int v = edge[i].to;
- if(v != son[u] && v != fa[u])
- build_tree(v, v);
- }
- }
- ll sum[MAXN];
- void pushUp(int rt) {
- sum[rt] = sum[rt << ] + sum[rt << | ];
- }
- void build(int l, int r, int rt) {
- sum[rt] = ;
- if(l == r) return;
- int m = (l + r) / ;
- build(lson); build(rson);
- }
- void update(int p, int c, int l, int r, int rt) {
- if(l == r) {
- sum[rt] = c;
- return;
- }
- int m = (l + r) / ;
- if(m >= p) update(p, c, lson);
- else update(p, c, rson);
- pushUp(rt);
- }
- ll query(int L, int R, int l, int r, int rt) {
- if(L <= l && R >= r) return sum[rt];
- int m = (l + r) / ;
- ll res = ;
- if(m >= L) res += query(L, R, lson);
- if(m < R) res += query(L, R, rson);
- return res;
- }
- void change(int v, int c) {
- if(dep[e[v].u] > dep[e[v].v]) update(w[e[v].u], c, , n, );
- else update(w[e[v].v], c, , n, );
- }
- ll seek(int v, int u) {
- int t1 = top[v], t2 = top[u];
- ll res = ;
- while(t1 != t2) {
- if(dep[t1] < dep[t2]) {
- swap(t1, t2); swap(v, u);
- }
- res += query(w[t1], w[v], , n, );
- v = fa[t1]; t1 = top[v];
- }
- if(v == u) return res;
- if(dep[v] > dep[u]) swap(v, u);
- return res + query(w[son[v]], w[u], , n, );
- }
- int main() {
- memset(head, -, sizeof head);
- cnt = num = ;
- scanf("%d%d%d", &n, &q, &s);
- for(int i = ; i < n; i++) {
- scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c);
- addedge(e[i].u, e[i].v);
- addedge(e[i].v, e[i].u);
- }
- dfs();
- build_tree(, );
- build(, n, );
- for(int i = ; i < n; i++) {
- if(dep[e[i].u] > dep[e[i].v]) update(w[e[i].u], e[i].c, , n, );
- else update(w[e[i].v], e[i].c, , n, );
- }
- while(q--) {
- int cc;
- int x, y;
- scanf("%d", &cc);
- if(cc) {
- scanf("%d%d", &x, &y);
- change(x, y);
- } else {
- scanf("%d", &x);
- printf("%lld\n", seek(s, x));
- s = x;
- }
- }
- return ;
- }
POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权的更多相关文章
- 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)
传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...
- 模拟赛 T3 DFS序+树状数组+树链的并+点权/边权技巧
题意:给定一颗树,有 $m$ 次操作. 操作 0 :向集合 $S$ 中加入一条路径 $(p,q)$,权值为 $v$ 操作 1 :给定一个点集 $T$,求 $T$ 的并集与 $S$ 中路径含交集的权和. ...
- HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)
Attack Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) Total Sub ...
- NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)
Problem 1050: Just Go Time Limits: 3000 MS Memory Limits: 65536 KB 64-bit interger IO format: % ...
- UOJ#291. 【ZJOI2017】树状数组 树套树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ291.html 题解 结论:这个写错的树状数组支持的是后缀加和后缀求和.这里的后缀求和在 x = 0 的时 ...
- hdu1556 树状数组区间更新单点查询板子
就是裸的区间更新: 相对于直观的线段树的区间更新,树状数组的区间更新原理不太相同:由于数组中的一个结点控制的是一块区间,当遇到更新[l,r]时,先将所有能控制到 l 的结点给更新了,这样一来就是一下子 ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- 【poj2155】Matrix(二维树状数组区间更新+单点查询)
Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...
- hdu-3584 Cube---三维树状数组+区域更新单点查询
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3584 题目大意: 给定一个N*N*N多维数据集A,其元素是0或是1.A[i,j,k]表示集合中第 i ...
随机推荐
- opennebula 发送序列化ID,构造json格式错误
- linux下mariadb的下载与卸载
Linux下mariadb的安装 使用阿里云的mariadb yum install mariadb-server mariadb -y 启动mariadb数据库 systemctl start/st ...
- C# 随机数 Radom 循环生成同一的数字
错误:在一个循环结构中,利用下列代码生成随机数,发生生成的随机数是一样的! for (int i = 0; i < myArray.Length; i++) //给数组赋值 { Random m ...
- layui之弹出层--从父窗口传递数据到子窗口
原文链接:https://blog.csdn.net/Code_shadow/article/details/80524633 var Index = layer.open({ title: &quo ...
- 杨辉三角的Python实现
杨辉三角的Python实现 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 Python生成器实现杨辉三角: # python def yanghui_tr ...
- Kubernetes 集群部署(2) -- Etcd 集群
Kubenetes 集群部署规划: 192.168.137.81 Master 192.168.137.82 Node 192.168.137.83 Node 以下在 Master 节点操作. ...
- 通过 js 修改 html 的文本内容或者样式
通过 js 修改 html 的文本内容 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...
- 【bzoj3576】[Hnoi2014]江南乐 数论分块+博弈论
Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一个数F ...
- uoj #297. 【CTSC2017】密钥
#297. [CTSC2017]密钥 一个密钥是一个长度为 n=2k+1n=2k+1 的字符串,它包含 11 个字母X.kk 个字母 A 和 kk 个字母 B.例如 k=3k=3 时,BAXABAB ...
- WKWebView 的使用和封装
WKWebView 的使用和封装 前言 项目中有个新闻资讯模块展示公司和相关行业的最新动态. 这个部分基本是以展示网页为主,内部可能会有一些 native 和 JS 代码的交互. 因为是新项目,所以决 ...