P4114 Qtree1
P4114 Qtree1
题解
树链剖分的恶心题目
1.读入边,连边存边
2.两遍DFS
第一遍找出每个点的重儿子 son fa size
第二遍更新 dfn dep top
3.把边权放到深度较大的结点上
4.线段树建树存边
5.线段树单点修改,区间查询
6.树链剖分查询的时候,一开始a,b路径可能是一个v形,然后不断跳跃重链,直到他们在一条重链上,然后两点中深度大的在下面,询问该区间的最大值
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<string> #include<cstring> #include<cstdlib> #include<queue> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int maxn=1e5+10; const int maxm=2e5+10; int n,cnt=0; struct nod { int u,v,w; }edge[maxm]; int head[maxn],to[maxm],nxt[maxm]; inline void addedge(int u,int v) { to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt; to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt; } int tim=0; int size[maxn],son[maxn],dfn[maxn],top[maxn],dep[maxn],fa[maxn]; void dfs1(int u,int f) { fa[u]=f; son[u]=0; size[u]=1; for(int i=head[u],v;i;i=nxt[i]) { if(v=to[i] ,v!=f) { dfs1(v,u); size[u]+=size[v]; if(size[v]>size[son[u]]) son[u]=v; } } } void dfs2(int u,int f) { tim++; dfn[u]=tim; dep[u]=dep[f]+1; top[u]= (u==son[f] ? top[f] : u); if(son[u]!=0) dfs2(son[u],u); for(int i=head[u],v;i;i=nxt[i]) { if(v=to[i],v!=f&&v!=son[u]) dfs2(v,u); } } int val[maxn]; int zd[maxn<<2]; void modify(int k,int l,int r,int p,int v) { if(l==r) { zd[k]=v;return; } else { int mid=(l+r)>>1; if(p<=mid) modify(k<<1,l,mid,p,v); else modify(k<<1|1,mid+1,r,p,v); zd[k]=max(zd[k<<1],zd[k<<1|1]); } } int query(int k,int l,int r,int x,int y) { if(x>y||y<l||x>r) return 0; if(x<=l&&r<=y) return zd[k]; else { int mid=(l+r)>>1; return max(query(k<<1,l,mid,x,y), query(k<<1|1,mid+1,r,x,y)); } } int query(int a,int b) { int ans=0; int ta=top[a],tb=top[b]; while(ta!=tb) { if(dep[ta]>dep[tb]) ans=max(ans,query(1,1,n,dfn[ta],dfn[a])),ta=top[a=fa[ta]]; else ans=max(ans,query(1,1,n,dfn[tb],dfn[b])),tb=top[b=fa[tb]]; } if(dep[a]>dep[b]) swap(a,b); return max(ans,query(1,1,n,dfn[a]+1,dfn[b])); } int main() { n=read(); for(int i=1;i<n;i++) { edge[i].u =read(); edge[i].v =read(); edge[i].w =read(); addedge(edge[i].u ,edge[i].v ); } dfs1(1,0); dfs2(1,0); for(int i=1;i<n;i++) { if(dep[edge[i].u] >dep[edge[i].v ]) swap(edge[i].u ,edge[i].v ); val[edge[i].v ]=edge[i].w ; } for(int i=1;i<=n;i++) modify(1,1,n,dfn[i],val[i]); char s[10]; while(scanf("%s",s),s[0]!='D') { int a,b; a=read();b=read(); if(s[0]=='Q') printf("%d\n",query(a,b)); if(s[0]=='C') modify(1,1,n,dfn[edge[a].v ],b); } return 0; }