P4114 Qtree1
分析
考查知识点
LCA+树剖+线段树
倒也不算难,我们看到,要做树上的单点修改,并且需要动态的知道一条路径上的最大值。
那就是这三个知识点了,因为如果若是一段连续的区间,那就不用LCA了,直接线段树+树剖就可以做了
利用树剖,将树拆成区间问题,同时还能去做LCA。
这里想说的是,如何存边。
不难想到,我们将边的权值转化为维护节点的权值,每个节点维护的是其上面的那条边。
但是有一个小问题,此时我们就不能将LCA的点权纳入考虑了,因为LCA是其上边的边的边权。
解决方案也很好想,有树剖LCA的特点,因此只需分两种情况
- 两个点不是一个点,那到最后时,两个点一定不会是一个点,此时只需要将深度较小的点(即LCA)的编号+1,再查询即可
- 若是一个点,那就直接输出0(如果不加特判,将会死循环,因为l>r了)
AC_code
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10,M = N*2;
struct Node
{
int l,r,mmax;
}tr[N<<2];
int h[N],e[M],ne[M],w[M],idx;
int id[N],nw[N],top[N],ts;
int son[N],fa[N],val[N],e2u[N],dep[N],sz[N];
int n;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
void dfs1(int u,int pa,int depth)
{
sz[u] = 1,fa[u] = pa,dep[u] = depth;
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==pa) continue;
val[j] = i/2+1;
e2u[i/2+1] = j;
dfs1(j,u,depth+1);
if(sz[son[u]]<sz[j]) son[u] = j;
sz[u] += sz[j];
}
}
void dfs2(int u,int tp)
{
id[u] = ++ts,top[u] = tp,nw[ts] = w[val[u]];
if(!son[u]) return ;
dfs2(son[u],tp);
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==son[u]||j==fa[u]) continue;
dfs2(j,j);
}
}
void pushup(int u)
{
tr[u].mmax = max(tr[u<<1].mmax,tr[u<<1|1].mmax);
}
void build(int u,int l,int r)
{
if(l==r)
{
tr[u] = {l,r,nw[l]};
return ;
}
tr[u] = {l,r,0};
int mid = l + r >> 1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
void modify(int u,int l,int r,int k)
{
if(l<=tr[u].l&&tr[u].r<=r)
{
tr[u].mmax = k;
return ;
}
int mid = tr[u].l + tr[u].r >> 1;
if(l<=mid) modify(u<<1,l,r,k);
if(r>mid) modify(u<<1|1,l,r,k);
pushup(u);
}
int query(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r) return tr[u].mmax;
int mid = tr[u].l + tr[u].r >> 1;
int res = 0;
if(l<=mid) res = max(res,query(u<<1,l,r));
if(r>mid) res = max(res,query(u<<1|1,l,r));
return res;
}
int main()
{
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++)
{
int a,b,c;cin>>a>>b>>c;
w[i+1] = c;
add(a,b),add(b,a);
}
dfs1(1,-1,1);
dfs2(1,1);
build(1,1,n);
string s;
while(cin>>s)
{
if(s=="DONE") break;
int x,y;cin>>x>>y;
if(s=="CHANGE") modify(1,id[e2u[x]],id[e2u[x]],y);
else
{
int res = 0;
if(x!=y){
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res = max(res,query(1,id[top[x]],id[x]));
x = fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
res = max(res,query(1,id[y]+1,id[x]));
}
cout<<res<<endl;
}
}
return 0;
}