SPOJ 375 Query on a tree【树链剖分】
2015-03-15 17:37
363 查看
题目大意:给你一棵树,有两个操作1.修改一条边的值,2.询问从x到y路径上边的最大值
思路:如果树退化成一条链的话线段树就很明显了,然后这题就是套了个树连剖分,调了很久终于调出来第一个模板了
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100009 using namespace std; int head[maxn],next[maxn*2],point[maxn],son[maxn],size_k[maxn],id[maxn],value[maxn],now=0,father[maxn],top[maxn]; int x[maxn],y[maxn],v[maxn],tree[maxn*4],pos=0,deep[maxn],n; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void add(int x,int y,int v) { next[++now]=head[x];head[x]=now; point[now]=y;value[now]=v; } int dfs(int k,int fa) { deep[k]=deep[fa]+1; father[k]=fa; size_k[k]=1; int max_x=-1; son[k]=-1; for(int i=head[k];i;i=next[i]) { if(point[i]==fa)continue; dfs(point[i],k); size_k[k]+=size_k[point[i]]; if(size_k[point[i]]>max_x) { max_x=size_k[point[i]]; son[k]=point[i]; } } } void dfs2(int k,int fa,int pa) { id[k]=++pos; top[k]=pa; if(son[k]!=-1)dfs2(son[k],k,pa); for(int i=head[k];i;i=next[i]) { if(point[i]!=fa && point[i]!=son[k])dfs2(point[i],k,point[i]); } } void update(int node,int l,int r,int pos,int x) { if(l+1==r){tree[node]=x;return;} int mid=(l+r)>>1; if(pos<mid)update(node*2,l,mid,pos,x); else update(node*2+1,mid,r,pos,x); tree[node]=max(tree[node*2],tree[node*2+1]); } int query(int node,int l,int r,int ql,int qr) { if(ql<=l && r<=qr)return tree[node]; int mid=(l+r)>>1; int ans=-0x3f3f3f3f; if(ql<mid)ans=max(query(node<<1,l,mid,ql,qr),ans); if(mid<qr)ans=max(query(node<<1|1,mid,r,ql,qr),ans); return ans; } int find(int x,int y) { int fa=top[x],fb=top[y],temp=0; while(fa!=fb) { if(deep[fa]<deep[fb]) { swap(fa,fb); swap(x,y); } if(id[fa]>id[x]+1)return -1; temp=max(temp,query(1,1,pos+1,id[fa],id[x]+1)); x=father[fa];fa=top[x]; } if(x==y)return temp; if(deep[x]<deep[y])swap(x,y); if(id[y]+1>id[x]+1)return -1; return max(temp,query(1,1,pos+1,id[son[y]],id[x]+1)); } int main() { int t; t=read(); while(t--) { now=0; memset(head,0,sizeof(head)); memset(tree,0,sizeof(tree)); n=read(); for(int i=1;i<n;i++) { x[i]=read();y[i]=read();v[i]=read(); add(x[i],y[i],v[i]); add(y[i],x[i],v[i]); } deep[1]=0; dfs(1,0); dfs2(1,1,1); for(int i=1;i<=n-1;i++) { int u=deep[x[i]]>deep[y[i]]?x[i]:y[i]; update(1,1,pos+1,id[u],v[i]); } int xx,yy; char ch[100]; while(true) { scanf("%s",ch); if(ch[0]=='D')break; xx=read();yy=read(); if(ch[0]=='Q') { printf("%d\n",find(xx,yy)); } else if(ch[0]=='C') { int u=deep[x[xx]]>deep[y[xx]]?x[xx]:y[xx]; update(1,1,pos+1,id[u],yy); } else if(ch[0]=='D') { break; } } } return 0; }
相关文章推荐
- SPOJ375 Query on a tree(树链剖分)
- Spoj375 Query on a tree 裸·树链剖分
- spoj375 Query on a tree(树链剖分 边权 入门题)
- spoj 375 Query on a tree(树链剖分,线段树)
- spoj 375 QTREE - Query on a tree 树链剖分 LCT 动态树
- SPOJ 375 Query on a tree(树链剖分)
- 【树链剖分】spoj375 Query on a tree
- spoj 375 Query on a tree 树链剖分
- SPOJ 375 Query on a tree(初学树链剖分)
- 【树链剖分】SPOJ 375 Query on a tree 裸题
- 【spoj375】Query on a tree【树链剖分】【或者动态树,那样常数就完了T_T】
- 树链剖分 spoj 375 Query on a tree(剖分入门)
- spoj 375 Query on a tree(树链剖分,边,线段树)
- SPOJ-375 QTREE - Query on a tree (树链剖分 边权转点权)
- SPOJ 375 query on a tree 树链剖分
- SPOJ 375 树链剖分 QTREE - Query on a tree
- 【SPOJ】375 Query on a tree QTREE系列之1 树链剖分
- spoj375 Query on a tree 树链剖分
- spoj 375 Query on a tree(树链剖分)
- spoj375 Query on a tree(树链剖分)