• 洛谷 P3979 遥远的国度


    题目描述

    修改某条路径上的值以及询问子树的最小值都最树剖的基础操作,那么如何实现换根呢?

    考虑一下三种情况:

    1.rot=询问的子树x,答案就是整棵树的最小值
    2.rot在x的子树里,只有rot到x这一条链上的的节点的子树会变
    找到x在rot方向上的子节点,答案就是除去这棵子树的最小值
    3.rot不在x的子树里,那么rot是谁对x的子树没有影响,答案不变

    那么就在询问时分类讨论一下就好了

    #include<complex>
    #include<cstdio>
    using namespace std;
    const int INF=1<<30;
    const int N=1e5+7;
    struct node{
        int v,nxt;
    }e[N<<1];
    int n,m,s,Enum,tim,rot;
    int val[N],front[N],fa[N][20];
    int fat[N],dep[N],tid[N],son[N],siz[N],top[N],rank[N];
    int tree[N<<2],lazy[N<<2];
    inline int qread()
    {
        int x=0,j=1;
        char ch=getchar();
        while(ch<'0' || ch>'9'){if(ch=='-')j=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*j;
    }
    inline void Insert(int u,int v)
    {
        e[++Enum].v=v;
        e[Enum].nxt=front[u];
        front[u]=Enum;
    }
    void dfs1(int x)
    {
        siz[x]=1;
        fa[x][0]=fat[x];
        for(int i=front[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(v==fat[x])continue;
            fat[v]=x;
            dep[v]=dep[x]+1;
            dfs1(v);
            siz[x]+=siz[v];
            if(siz[v]>siz[son[x]])
                son[x]=v;
        }
    }
    void dfs2(int x,int tp)
    {
        top[x]=tp;
        tid[x]=++tim;
        rank[tid[x]]=x;
        if(!son[x])return;
        dfs2(son[x],tp);
        for(int i=front[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(v!=son[x] && v!=fat[x])
                dfs2(v,v);
        }
    }
    inline void PushUp(int rt)
    {
        tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
    }
    inline void PushDown(int rt)
    {
        if(lazy[rt])
        {
            tree[rt<<1]=tree[rt<<1|1]=lazy[rt];
            lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
            lazy[rt]=0;
        }
    }
    void Build(int l,int r,int rt)
    {
        if(l==r)
        {
            tree[rt]=val[rank[l]];
            return;
        }
        int mid=l+r>>1;
        Build(l,mid,rt<<1);
        Build(mid+1,r,rt<<1|1);
        PushUp(rt);
    }
    void Modify(int l,int r,int rt,int nowl,int nowr,int v)
    {
        if(nowl<=l && r<=nowr)
        {
            tree[rt]=lazy[rt]=v;
            return;
        }
        PushDown(rt);
        int mid=l+r>>1;
        if(nowl<=mid)Modify(l,mid,rt<<1,nowl,nowr,v);
        if(mid<nowr)Modify(mid+1,r,rt<<1|1,nowl,nowr,v);
        PushUp(rt);
    }
    int Query(int l,int r,int rt,int nowl,int nowr)
    {
        if(nowl<=l && r<=nowr)
            return tree[rt];
        PushDown(rt);
        int mid=l+r>>1,a=INF,b=INF;
        if(nowl<=mid)a=Query(l,mid,rt<<1,nowl,nowr);
        if(mid<nowr)b=Query(mid+1,r,rt<<1|1,nowl,nowr);
        return min(a,b);
    }
    void FindFather()
    {
        for(int j=1;j<=19;j++)
            for(int i=1;i<=n;i++)
                fa[i][j]=fa[fa[i][j-1]][j-1];
    }
    inline int Lca(int a,int b)
    {
        if(dep[a]<dep[b])swap(a,b);
        int tmp=dep[a]-dep[b];
        for(int i=19;i>=0;i--)
            if(tmp&(1<<i))
                a=fa[a][i];
        if(a==b)return a;
        for(int i=19;i>=0;i--)
            if(fa[a][i]!=fa[b][i])
            {
                a=fa[a][i];
                b=fa[b][i];
            }
        return fa[a][0];
    }
    inline void ModifyRoad(int x,int y,int v)
    {
        int f1=top[x],f2=top[y];
        while(f1!=f2)
        {
            if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);
            Modify(1,n,1,tid[f1],tid[x],v);
            x=fat[f1];f1=top[x];
        }
        if(dep[x]>dep[y])swap(x,y);
        Modify(1,n,1,tid[x],tid[y],v);
    }
    inline int QueryTree(int x)
    {
        if(x==rot)return tree[1];
        int lca=Lca(x,rot);
        if(lca==x)
        {
            int tmp=dep[rot]-dep[x]-1,v=rot;
            for(int i=0;i<=19;i++)
                if(tmp&(1<<i))
                    v=fa[v][i];
            return min(Query(1,n,1,1,tid[v]-1),Query(1,n,1,tid[v]+siz[v],n));
        }
        return Query(1,n,1,tid[x],tid[x]+siz[x]-1);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int u,v,p,x;
        for(int i=1;i<=n-1;i++)
        {
            u=qread();v=qread();
            Insert(u,v);
            Insert(v,u);
        }
        for(int i=1;i<=n;i++)
            val[i]=qread();
        dfs1(1);dfs2(1,1);
        Build(1,n,1);
        FindFather();
        scanf("%d",&rot);
        for(int i=1;i<=m;i++)
        {
            p=qread();
            if(p==1)rot=qread();
            if(p==2)
            {
                u=qread();v=qread();x=qread();
                ModifyRoad(u,v,x);
            }
            if(p==3)
            {
                x=qread();
                printf("%d\n",QueryTree(x));
            }
        }
        return 0;
    }
  • 相关阅读:
    【MongoDB】 C#官方驱动增删查改
    【MongoDB】MongoHelper
    【设计模式】简单的单例模式
    andriod深度探索及驱动开发展望
    搭建Android开发环境
    第一章Android系统移植与驱动开发概述
    时间
    django-admin和manage.py
    自定义django-admin命令
    会话session
  • 原文地址:https://www.cnblogs.com/LeTri/p/8531082.html
Copyright © 2020-2023  润新知