P4114 Qtree1

P4114 Qtree1

分析

考查知识点

LCA+树剖+线段树

倒也不算难,我们看到,要做树上的单点修改,并且需要动态的知道一条路径上的最大值。

那就是这三个知识点了,因为如果若是一段连续的区间,那就不用LCA了,直接线段树+树剖就可以做了

利用树剖,将树拆成区间问题,同时还能去做LCA。

这里想说的是,如何存边。

不难想到,我们将边的权值转化为维护节点的权值,每个节点维护的是其上面的那条边。

但是有一个小问题,此时我们就不能将LCA的点权纳入考虑了,因为LCA是其上边的边的边权。

解决方案也很好想,有树剖LCA的特点,因此只需分两种情况

  1. 两个点不是一个点,那到最后时,两个点一定不会是一个点,此时只需要将深度较小的点(即LCA)的编号+1,再查询即可
  2. 若是一个点,那就直接输出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;
}
posted @ 2022-03-19 22:15  艾特玖  阅读(25)  评论(0编辑  收藏  举报