FZU 2082 求树上任意点间距离 边权转为点权 树链剖分
来源:互联网 发布:windows程序视频 编辑:程序博客网 时间:2024/05/22 03:35
题目链接:http://acm.fzu.edu.cn/problem.php?pid=2082
wushen博客:wuyiqi
思路:
边权转点权:
由于线段树中的点是节点,则把题目给的边权值作为 边一端 距离根更远的节点的点权值。
直接设置根权值为0 这样不会影响题意。
因为求的的是两点间所有的点权和,所以要减去 LCA(u,v),因为这个点所代表的边是没有在路径上的。
#include<stdio.h>#include<iostream>#include<string.h>using namespace std;#define N 50050#define L(x) (x<<1)#define R(x) (x<<1|1)#define Mid(x,y) ((x+y)>>1)#define ll __int64struct Edge{ll from, to, dis,nex;bool yes;}edge[N<<1];ll head[N], edgenum;ll dis[N];void addedge(ll u, ll v, ll d){Edge E={u,v,d,head[u],false};edge[edgenum] = E;head[u] = edgenum++;}ll son[N];ll top[N];ll fp[N];ll p[N];ll siz[N];ll dep[N];ll fa[N];ll tree_id;void dfs(ll u, ll father, ll deep){fa[u] = father; dep[u] = deep;siz[u] = 1;for(ll i = head[u]; ~i; i = edge[i].nex){ll v = edge[i].to; if(v == father)continue;dfs(v, u, deep+1);siz[u] += siz[v];if(son[u] == -1 || siz[son[u]]<siz[v])son[u] = v;dis[v] = edge[i].dis;edge[i].yes = true;}}void getpos(ll u, ll toppos){p[u] = tree_id++; fp[p[u]] = u;top[u] = toppos;if(son[u] == -1)return;if(u==0)getpos(son[u],son[u]);else getpos(son[u], toppos);for(int i = head[u]; ~i; i = edge[i].nex){int v = edge[i].to; if(v == fa[u] || v == son[u])continue;getpos(v,v);}}struct node{ll l, r;ll sum;}tree[N*8];void updata_up(ll id){tree[id].sum = tree[L(id)].sum+tree[R(id)].sum;}void build(ll l, ll r, ll id){tree[id].l = l, tree[id].r = r;tree[id].sum = 0;if(l == r)return ;int mid = Mid(l,r);build(l,mid,L(id)), build(mid+1,r,R(id));}void updata(ll pos, ll val, ll id){if(tree[id].l == tree[id].r){tree[id].sum = val;return;}ll mid = Mid(tree[id].l,tree[id].r);if(pos <= mid)updata(pos, val, L(id));else updata(pos, val, R(id));updata_up(id);}ll query(ll l, ll r, ll id){if(l <= tree[id].l && tree[id].r <= r)return tree[id].sum;ll mid = Mid(tree[id].l, tree[id].r);ll ans = 0;if(l <= mid)ans+=query(l,r,L(id));if(r > mid)ans+=query(l,r,R(id));return ans;}ll Query(ll x,ll y){ //让x在y下面ll f1 = top[x], f2 = top[y];ll ans = 0;while(f1 != f2){if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);ans += query(p[f1],p[x],1);x = fa[f1];f1 = top[x];}if(dep[x] > dep[y])swap(x,y);return ans + query(p[x],p[y],1) - query(p[x],p[x],1);;}void change(ll pos, ll val){Edge &E = edge[pos<<1]; if(E.yes == false) E = edge[pos<<1|1];E.dis = val;updata(p[E.to], val, 1);}ll n, m;void init(){memset(head, -1, sizeof(head)), edgenum = 0;memset(son, -1, sizeof(son));tree_id = 1;}int main(){ll i, j, u, v, d;while(~scanf("%I64d %I64d",&n,&m)){init();for(i = 1; i < n; i++) {scanf("%I64d %I64d %I64d",&u,&v,&d);addedge(u,v,d);addedge(v,u,d);}dfs(1,1,0);getpos(1,1);build(1,n,1); //建立虚拟根节点1updata(p[1],0,1);for(i = 2; i <= n; i++)updata(p[i],dis[i],1);while(m--){scanf("%I64d %I64d %I64d",&d,&u,&v);if(d == 0)change(u-1,v);else printf("%I64d\n",Query(u,v));}}return 0;}/*7 997 1 11 2 21 3 32 6 42 4 53 5 61 6 31 2 51 4 51 1 51 7 50 1 1001 7 50 6 1001 3 51 5 31 5 4*/
0 0
- FZU 2082 求树上任意点间距离 边权转为点权 树链剖分
- hdu 2196 computer 求树上的任意最远点对 O(n)
- HDU 2586 How far away (LCA模板题 树上点对间距离)
- Spoj 6779 Can you answer these queries VII 树链剖分 在树上任意路径的最大子段和 区间修改点权
- 数据点间距离公式
- 【OI杂记】求二叉树上任意两点的最短路径上的边权最大值
- 计算git树上任意两点的最近分割点。
- HDU 2376(树上任意2点间的距离)
- loj 1257 (求树上每一个点到树上另一个点的最长距离)
- 已知矩形的任意三个点,求第四个点
- HDU 2196 Computer(求树任意点的最远点)
- hdu2196(求每一点在树上最远距离)
- 两坐标点间距离公式
- poj1741 树上点分治
- POJ1741Tree(树上点分治)
- 树上点分治入门
- 求任意多边形的内点的算法
- 如何求曲线上任意点到端点的距离
- Git初识与使用
- Java基础 之软引用、弱引用、虚引用
- 二分查找自我总结
- <string> 与<string.h>、<cstring>的区别
- html5 特性介绍
- FZU 2082 求树上任意点间距离 边权转为点权 树链剖分
- Maven学习笔记之maven的生命周期
- 畅通工程续
- hdu3172
- 插入排序
- Maven学习笔记之maven插件的配置
- zend studio10.6配置xdebug版本是否线程安全
- ZDAPP_CONFIG_PAN_ID
- 关于一个c语言中的小陷阱(数据类型之间的转换)