【模板】【SPOJ375】树链剖分
来源:互联网 发布:网络教育本科统考 编辑:程序博客网 时间:2024/05/16 17:21
题目链接:https://vjudge.net/problem/SPOJ-QTREE
不错的Blog:
初学http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
练习https://vjudge.net/contest/28982
练习https://oi.abcdabcd987.com/summary-of-heavy-light-decomposition/
SPOJ375
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define getmid int m=(c[rt].l+c[rt].r)>>1using namespace std;///基于边权,修改单条边///查询路径边权最大值const int maxn=10010;int n;struct Edge{ int to,nxt;}e[maxn*2];struct segtree{ int l,r; int Max;}c[maxn*4+5];int head[maxn],ecnt;int top[maxn];///top[v]表示v所在链的顶端结点int fa[maxn]; ///父节点int dep[maxn]; ///深度int siz[maxn]; ///siz[v]表示以v为根的子树的结点树int id[maxn];///id[v]表示v与其父节点的连边在线段树中的位置int real[maxn]; ///表示线段树中的某个位置对应的边的起始编号int son[maxn]; ///son[u]表示u的重儿子int dfn;int d[maxn][3];void init(){ ecnt=dfn=0; memset(head,-1,sizeof(head)); memset(son,0,sizeof(son));}void add_edge(int u,int v){ e[++ecnt].nxt=head[u]; e[ecnt].to=v; head[u]=ecnt;}void dfs1(int u,int f,int d){ int v; dep[u]=d; fa[u]=f; siz[u]=1; for(int i=head[u];i!=-1;i=e[i].nxt) if((v=e[i].to)!=f) { dfs1(v,u,d+1); siz[u]+=siz[v]; if(!son[u]||siz[son[u]]<siz[v]) son[u]=v; }}void dfs2(int u,int tp){ int v; top[u]=tp; id[u]=++dfn; real[id[u]]=u; if(!son[u]) return; dfs2(son[u],tp); for(int i=head[u];i!=-1;i=e[i].nxt) if((v=e[i].to)!=son[u]&&v!=fa[u]) dfs2(v,v);}void Build(int l,int r,int rt){ c[rt].l=l; c[rt].r=r; c[rt].Max=0; if(l==r) return; int m=(l+r)>>1; Build(l,m,rt<<1); Build(m+1,r,rt<<1|1);}void Pushup(int rt){ c[rt].Max=max(c[rt<<1].Max,c[rt<<1|1].Max);}void Update(int rt,int k,int val){ if(c[rt].l==k&&c[rt].r==k) { c[rt].Max=val; return; } getmid; if(k<=m) Update(rt<<1,k,val); else Update(rt<<1|1,k,val); Pushup(rt);}int Query(int rt,int L,int R){ if(L<=c[rt].l&&R>=c[rt].r) return c[rt].Max; getmid; int ret=0; if(L<=m) ret=max(ret,Query(rt<<1,L,R)); if(R>m) ret=max(ret,Query(rt<<1|1,L,R)); return ret;}int ask_e(int u,int v){ int f1,f2,tmp=0; while((f1=top[u])!=(f2=top[v])) { if(dep[f1]<dep[f2]) { swap(f1,f2); swap(u,v); } tmp=max(tmp,Query(1,id[f1],id[u])); u=fa[f1]; } if(u==v) return tmp; if(dep[u]>dep[v]) swap(u,v); return max(tmp,Query(1,id[son[u]],id[v]));}int main(){ int u,v; int T; cin>>T; while(T--) { init(); cin>>n; for(int i=1;i<=n-1;i++) { scanf("%d%d%d",&d[i][0],&d[i][1],&d[i][2]); add_edge(d[i][0],d[i][1]); add_edge(d[i][1],d[i][0]); } dfs1(1,0,1); dfs2(1,1); Build(1,dfn,1); for(int i=1;i<=n-1;i++) { if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]); Update(1,id[d[i][1]],d[i][2]); } char s[10]; while(scanf("%s",s)) { if(s[0]=='D') break; scanf("%d%d",&u,&v); if(s[0]=='Q') printf("%d\n",ask_e(u,v)); else Update(1,id[d[u][1]],v); } } return 0;}
阅读全文
0 0
- spoj375树链剖分模板
- 【模板】【SPOJ375】树链剖分
- SPOJ375(树链剖分)
- 树链剖分 spoj375
- spoj375 树链剖分
- spoj375 树链剖分
- 树链剖分-spoj375
- spoj375(树链剖分)
- SPOJ375 QTREE 树链剖分入门
- spoj375树链剖分 (链)
- 【spoj375】树链剖分 裸题
- spoj375
- SPOJ375——Query on a tree(树链剖分模板详解以及入门)
- SPOJ375--Query on a tree(树链剖分)
- spoj375 Query on a tree 树链剖分
- spoj375(树链剖分入门题) 链分治
- 树链剖分(spoj375)基于边权
- spoj375 Query on a tree 树链剖分
- shell字符串的截取
- pojFilp Game2965 翻转棋子
- shell里if-then的使用
- 阅读TF_IDF代码
- 【STL】hdu 4585 Shaolin
- 【模板】【SPOJ375】树链剖分
- Android事件分发理解
- 【caffe】windows下caffe+vs2013+python2.7+cuda8.0+cmake3.8编译与配置
- Ubuntu 改变用户名和主机名
- 我需要学习的东西
- 注册时:js的ajax实现局部刷新验证用户名
- 3D背景图动画阴影效果
- 【笔记】c c++如何打印变量地址
- 使用busybox制作Linux文件系统(一)