spoj 375 QTREE - Query on a tree(树链剖分,边权)
2017-10-03 16:28
441 查看
边权的树链剖分,把边权都推到下边的点上,就是点权了,然后,根节点没有权值。
还是kuangbin大佬的模板。。。。
还是kuangbin大佬的模板。。。。
#include <bits/stdc++.h> //每条边两个点,把每条边的权值放到深度较深的那个点上,根节点无权值,就是方个最小值 const int MAXN = 10010; struct Edge { int to,next; } edge[MAXN*2]; int head[MAXN],tot; int top[MAXN];//top[v]表示v所在的重链的顶端节点 int fa[MAXN]; //父亲节点 int dep[MAXN];//深度 int num[MAXN];//num[v]表示以v为根的子树的节点数 int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置 int fp[MAXN];//和p数组相反 int son[MAXN];//重儿子 int pos; int e[MAXN][3]; void init() { tot = 0; memset(head,-1,sizeof(head)); pos = 0; memset(son,-1,sizeof(son)); } void addedge(int u,int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs1(int u, int pre, int d) { dep[u] = d; fa[u] = pre; num[u] = 1; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == pre) continue; dfs1(v,u,d+1); num[u] += num[v]; if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v; } } void getpos(int u, int sp) { top[u] = sp; p[u] = pos++; if(son[u] == -1) return; getpos(son[u],sp); for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v != son[u] && v != fa[u]) getpos(v,v); } } struct Node { int l,r; int Max; }segTree[MAXN*3]; void build(int i, int l, int r) { segTree[i].l = l; segTree[i].r = r; segTree[i].Max = 0; if(l == r) return; int mid = (l+r) >> 1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); } void push_up(int i) { segTree[i].Max = std::max(segTree[i<<1].Max,segTree[(i<<1)|1].Max); } void update(int i, int k, int val)// 更新线段树的第k个值为val { if(segTree[i].l == k && segTree[i].r == k) { segTree[i].Max = val; return; } int mid = (segTree[i].l + segTree[i].r) >> 1; if(k <= mid) update(i<<1,k,val); else update(i<<1|1,k,val); push_up(i); } int query(int i, int l, int r) { if(segTree[i].l == l && segTree[i].r == r) return segTree[i].Max; int mid = (segTree[i].l + segTree[i].r) >> 1; if(r <= mid) return query(i<<1, l, r); else if(l > mid) return query(i<<1|1, l, r); else return std::max(query(i<<1,l , mid), query(i<<1|1, mid+1, r)); } int find(int u, int v) { int f1 = top[u], f2 = top[v]; int tmp = 0; while(f1 != f2) { if(dep[f1] < dep[f2]) { std::swap(f1,f2); std::swap(u,v); } tmp = std::max(tmp,query(1,p[f1],p[u])); u = fa[f1]; f1 = top[u]; } if(u == v) return tmp; if(dep[u] > dep[v]) std::swap(u,v); //因为边权都被推到下边的点上了,所以u->v的边权最值,就是son[u]->v的点权值 return std::max(tmp,query(1,p[son[u]],p[v])); } int main() { int T; int n; scanf("%d",&T); while(T--) { init(); scanf("%d",&n); for(int i = 0; i < n-1; ++i) { scanf("%d %d %d",&e[i][0],&e[i][1],&e[i][2]); addedge(e[i][0],e[i][1]); addedge(e[i][1],e[i][0]); } dfs1(1,0,0); getpos(1,1); build(1,0,pos-1); for(int i = 0; i < n-1; ++i) { if(dep[e[i][0]] > dep[e[i][1]]) std::swap(e[i][0],e[i][1]); update(1,p[e[i][1]],e[i][2]); } char op[10]; int u,v; while(scanf(" %s",op)) { if(op[0] == 'D') break; scanf("%d %d",&u,&v); if(op[0] == 'Q') printf("%d\n",find(u,v)); else update(1,p[e[u-1][1]],v); } } return 0; }
相关文章推荐
- SPOJ 375 QTREE系列-Query on a tree (树链剖分)
- SPOJ 题目 375 QTREE - Query on a tree(树链剖分)
- SPOJ 375 QTREE Query on a tree 树链剖分水题
- SPOJ 375 QTREE - Query on a tree 树链剖分+线段树(单点更新 区间查询最值)
- spoj 375 QTREE - Query on a tree 树链剖分 LCT 动态树
- 【SPOJ】375 Query on a tree QTREE系列之1 树链剖分
- SPOJ 375 Query on a tree(树链剖分)(QTREE)
- SPOJ-375 QTREE - Query on a tree (树链剖分 边权转点权)
- SPOJ 375 树链剖分 QTREE - Query on a tree
- 【SPOJ】QTREE - Query on a tree(树链剖分+线段树(基于边权))
- SPOJ 375 Query on a tree【树链剖分】
- spoj375 Query on a tree(树链剖分)
- 【SPOJ375】Query on a tree-树链剖分
- spoj 375 Query on a tree 树链剖分
- SPOJ QTREE - Query on a tree(树链剖分)
- [SPOJ375] QTREE - Query on a tree
- SPOJ QTREE Query on a tree --树链剖分
- 【树链剖分】spoj375 Query on a tree
- 【SPOJ】2798 Query on a tree again! QTREE系列之3 树链剖分
- [SPOJ 375]Query On a Tree(树链剖分)