树链剖分【p4114】Qtree-Query on a tree I
2018-10-20 19:32
239 查看
Description
给定一棵n个节点的树,有两个操作:
- CHANGE i ti 把第i条边的边权变成ti
- QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0
Input
第一行输入一个n,表示节点个数
第二行到第n行每行输入三个数,ui,vi,wi,分别表示 ui,vi有一条边,边权是wi
第n+1行开始,一共有不定数量行,每一行分别有以下三种可能
CHANGE,QUERY同题意所述
DONE表示输入结束
Output
对于每个QUERY操作,输出一个数,表示a b之间边权最大值
裸的树链剖分题.
将边权转为点权要赋给深度较深的点,这样可以保证一个点权对应一个边权.
注意题目中的\(a==b\)的时候输出\(0\),要不就一遍切了 QAQ.
代码
#include<cstdio> #include<cstring> #include<iostream> #include<cctype> #define int long long #define N 100008 #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,head ,tot; struct cod{int u,v,w,fr;}edge[N<<2]; inline void add(int x,int y,int z) { edge[++tot].u=head[x]; edge[tot].fr=x; edge[tot].v=y; edge[tot].w=z; head[x]=tot; } int son ,size ,f ,depth ,val ; char s[108]; void dfs1(int u,int fa,int dis) { f[u]=fa;depth[u]=depth[fa]+1;size[u]=1;val[u]=dis; for(R int i=head[u];i;i=edge[i].u) { if(edge[i].v==fa)continue; dfs1(edge[i].v,u,edge[i].w); size[u]+=size[edge[i].v]; if(son[u]==-1 or size[son[u]]<son[edge[i].v]) son[u]=edge[i].v; } } int top ,idx,dfn ,fdfn ; void dfs2(int u,int t) { top[u]=t;dfn[u]=++idx;fdfn[idx]=u; if(son[u]==-1)return; dfs2(son[u],t); for(R int i=head[u];i;i=edge[i].u) { if(dfn[edge[i].v])continue; dfs2(edge[i].v,edge[i].v); } } int tr[N<<2]; #define ls o<<1 #define rs o<<1|1 inline void up(int o){tr[o]=max(tr[ls],tr[rs]);} void build(int o,int l,int r) { if(l==r) { tr[o]=val[fdfn[l]]; return; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); up(o); } void change(int o,int l,int r,int pos,int z) { if(l==r){tr[o]=z;return;} int mid=(l+r)>>1; if(pos<=mid)change(ls,l,mid,pos,z); else change(rs,mid+1,r,pos,z); up(o); } int query(int o,int l,int r,int x,int y) { if(x<=l and y>=r)return tr[o]; int mid=(l+r)>>1,res=-214748364766LL; if(x<=mid)res=max(res,query(ls,l,mid,x,y)); if(y>mid)res=max(res,query(rs,mid+1,r,x,y)); return res; } inline int tquery(int x,int y) { int fx=top[x],fy=top[y],res=-214748364766LL; while(fx!=fy) { if(depth[fx]>depth[fy]) { res=max(res,query(1,1,n,dfn[fx],dfn[x])); x=f[fx]; } else { res=max(res,query(1,1,n,dfn[fy],dfn[y])); y=f[fy]; } fx=top[x],fy=top[y]; } if(x==y)return res; if(dfn[x]>dfn[y])swap(x,y); res=max(res,query(1,1,n,dfn[x]+1,dfn[y])); return res; } signed main() { in(n);memset(son,-1,sizeof son); for(R int i=1,x,y,z;i<n;i++) { in(x),in(y),in(z); add(x,y,z);add(y,x,z); } dfs1(1,0,0);dfs2(1,1); build(1,1,n); for(R int x,y;;) { scanf("%s",s+1); if(s[1]=='D')break; if(s[1]=='Q') { in(x),in(y); if(x==y)puts("0"); else printf("%lld\n",tquery(x,y)); } else { in(x),in(y);x*=2; if(depth[edge[x].v]<depth[edge[x].fr]) x=edge[x].fr; else x=edge[x].v; change(1,1,n,dfn[x],y); } } }
相关文章推荐
- SPOJ 375 Query on a tree(树链剖分)(QTREE)
- [spoj QTREE Query on a tree]树链剖分
- 【SPOJ】QTREE - Query on a tree(树链剖分+线段树(基于边权))
- SPOJ 375 QTREE Query on a tree 树链剖分水题
- SPOJ QTREE Query on a tree (树链剖分)
- 【SPOJ】375 Query on a tree QTREE系列之1 树链剖分
- SPOJ QTREE Query on a tree(树链剖分-点更新-区间最值查询-入边)
- SPOJ-375 QTREE - Query on a tree (树链剖分 边权转点权)
- SPOJ QTREE - Query on a tree 【树链剖分模板】
- SPOJ QTREE- Query on a tree (树链剖分)
- 【SPOJ】2798 Query on a tree again! QTREE系列之3 树链剖分
- 树链剖分模板题-SPOJ QTREE Query on a tree
- SPOJ QTREE Query on a tree ——树链剖分 线段树
- SPOJ 375 树链剖分 QTREE - Query on a tree
- SPOJ - QTREE Query on a tree 树链剖分
- SPOJ QTREE Query on a tree --树链剖分
- SPOJ 题目 375 QTREE - Query on a tree(树链剖分)
- SPOJ375[QTREE - Query on a tree] 树链剖分
- SPOJ 375 QTREE系列-Query on a tree (树链剖分)
- [ SPOJ - QTREE]Query on a tree && 树链剖分