zoukankan      html  css  js  c++  java
  • bzoj 3083

    bzoj 3083 树链剖分,换根

    对于一颗树有以下操作

    1.确定x为根,2.将u到v的简单路径上的数全改成c,3.询问当前以x为根的子树中的节点最小权值。

    如果没有操作1:树链剖分很明显。

    于是考虑换根对结果的影响:

    Case 1:root=x 结果是全树最小值。

    Case 2: root!=x且lca(root,x)=x 利用倍增求出x的孩子中是root祖先的那一个设为y,结果是全树除子树y以外最小值。

    Case 3:lca(root,x)!=x 结果无影响,即子树x的最小值。

    简述:树链剖分&lca/倍增

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=2147483647;
    struct tr{int dep,sz,hs,tp,ls,rs,fa[18];}t[100005];
    struct st{int mn,tg;}seg[400005];
    vector<int>g[100005];
    int n,m,ans,rt,tt,v[400005],ps[100005];
    void dfs1(int x,int p,int d)
    {
        t[x].fa[0]=p;t[x].dep=d;t[x].hs=0;t[x].sz=1;
        for(int i=1;i<=17;i++)if(t[x].dep>=1<<i)t[x].fa[i]=t[t[x].fa[i-1]].fa[i-1];
        for(int i=0;i<g[x].size();i++)if(g[x][i]!=p)
        {
            dfs1(g[x][i],x,d+1);
            if(t[t[x].hs].sz<t[g[x][i]].sz)t[x].hs=g[x][i];
        }
    }
    void dfs2(int x,int p)
    {
        t[x].tp=p;t[x].ls=ps[x]=++tt;
        if(t[x].hs)dfs2(t[x].hs,p);
        for(int i=0;i<g[x].size();i++)if(g[x][i]!=t[x].fa[0]&&g[x][i]!=t[x].hs)dfs2(g[x][i],g[x][i]);
        t[x].rs=tt;
    }
    void up(int x){seg[x].mn=min(seg[x<<1].mn,seg[x<<1|1].mn);}
    void down(int x){seg[x<<1]=seg[x<<1|1]=seg[x];seg[x].tg=0;}
    void build(int x,int l,int r)
    {
        if(l==r){seg[x].mn=v[l];return;}
        int md=l+r>>1;build(x<<1,l,md);build(x<<1|1,md+1,r);up(x);
    }
    void upd(int x,int l,int r,int tl,int tr,int c)
    {
        if(tl<=l&&r<=tr){seg[x]=(st){c,c};return;}
        if(seg[x].tg)down(x);
        int md=l+r>>1;
        if(tl<=md)upd(x<<1,l,md,tl,tr,c);
        if(tr>md)upd(x<<1|1,md+1,r,tl,tr,c);
        up(x);
    }
    void qry(int x,int l,int r,int tl,int tr)
    {
        if(tl<=l&&r<=tr){ans=min(ans,seg[x].mn);return;}
        if(seg[x].tg)down(x);
        int md=l+r>>1;
        if(tl<=md)qry(x<<1,l,md,tl,tr);
        if(tr>md)qry(x<<1|1,md+1,r,tl,tr);
    }
    int gtlca(int x,int y)
    {
        if(t[x].dep<t[y].dep)swap(x,y);
        int sub=t[x].dep-t[y].dep;
        for(int i=0;i<=17;i++)if(sub&(1<<i))x=t[x].fa[i];
        for(int i=17;i>=0;i--)if(t[x].fa[i]!=t[y].fa[i])x=t[x].fa[i],y=t[y].fa[i];
        if(x==y)return x;else return t[x].fa[0];
    }
    int gtanc(int x,int d){for(int i=0;i<=17;i++)if(d&(1<<i))x=t[x].fa[i];return x;}
    void modify(int x,int y,int c)
    {
        int f1=t[x].tp,f2=t[y].tp;
        while(f1!=f2)
        {
            if(t[f1].dep<t[f2].dep){swap(f1,f2);swap(x,y);}
            upd(1,1,n,ps[f1],ps[x],c);
            x=t[f1].fa[0];f1=t[x].tp;
        }
        if(t[x].dep>t[y].dep)swap(x,y);
        upd(1,1,n,ps[x],ps[y],c);
    }
    void query(int x)
    {
        int lca,v;
        lca=gtlca(rt,x);
        if(rt==x)printf("%d
    ",seg[1].mn);
        else
        {
            ans=inf;
            if(lca!=x)qry(1,1,n,t[x].ls,t[x].rs);
            else
            {
                v=gtanc(rt,t[rt].dep-t[x].dep-1);
                if(t[v].ls>1)qry(1,1,n,1,t[v].ls-1);
                if(t[v].rs<n)qry(1,1,n,t[v].rs+1,n);
            }
            printf("%d
    ",ans);
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}
        dfs1(1,0,0);
        dfs2(1,1);
        for(int i=1;i<=n;i++)scanf("%d",&v[ps[i]]);
        build(1,1,n);
        scanf("%d",&rt);
        for(int i=1;i<=m;i++)
        {
            int kd,x,y,c;scanf("%d",&kd);
            if(kd==1)scanf("%d",&rt);
            else if(kd==2){scanf("%d%d%d",&x,&y,&c);modify(x,y,c);}
            else if(kd==3){scanf("%d",&x);query(x);}
        }
        return 0;
    } 
  • 相关阅读:
    [PHP动态]0001.关于 PHP 7 你必须知道的五件事
    [PHP工具推荐]0001.分析和解析代码的7大工具
    Java数据结构和算法(八)——递归
    Java数据结构和算法(七)——链表
    Java数据结构和算法(六)——前缀、中缀、后缀表达式
    Java数据结构和算法(五)——队列
    Java数据结构和算法(四)——栈
    Java数据结构和算法(三)——冒泡、选择、插入排序算法
    Java数据结构和算法(二)——数组
    Java数据结构和算法(一)——简介
  • 原文地址:https://www.cnblogs.com/xyleo/p/8604525.html
Copyright © 2011-2022 走看看