zoukankan      html  css  js  c++  java
  • [日常摸鱼]bzoj3083遥远的国度-树链剖分

    一无聊就找树剖写

    题意:一颗带点权的树,三种操作:1.换根 2.链赋值 3.查询子树最小值


    如果没有换根的话直接就是裸的树剖了,对于换根的操作我们可以分类讨论。

    1.如果查询的$x$就是根,那答案就是整棵树的最小值。

    2.如果以1为根的dfs序中,根在$x$的子树之外,那很明显$x$的子树还是原来的子树。

    3.如果以1为根的dfs序中,根在$x$的子树里面的话,画个图就能发现,找到$x$的孩子中作为根的父亲那个点,答案就是整棵树把整个点的子树去掉就行了。

    其他地方跟树剖没什么区别…

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long lint;
    const int N=100005;
    const lint INF=(1ll<<32);
    inline lint read()
    {
        lint s=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
        return s*f;
    }
    struct edge
    {
        int to,nxt;
    }edges[N<<1];
    int n,m,cnt,rot,tot;
    int head[N<<1],son[N],size[N],dep[N],top[N],dl[N],dr[N],rk[N],fa[N];
    lint tr[N<<2],tag[N<<2],v[N];
    
    #define lson (o<<1)
    #define rson (o<<1|1)
    inline void push_up(int o)
    {
        tr[o]=min(tr[lson],tr[rson]);
    }
    inline void push_down(int o)
    {
        if(tag[o]==-1)return;
        tag[lson]=tag[rson]=tag[o];
        tr[lson]=tr[rson]=tag[o];
        tag[o]=-1;
    }
    inline void build(int o,int l,int r)
    {
        tag[o]=-1;
        if(l==r)
        {
            tr[o]=v[rk[l]];
            return;
        }int mid=(l+r)>>1;
        build(lson,l,mid);build(rson,mid+1,r);
        push_up(o);
    }
    inline void modify(int o,int l,int r,int ql,int qr,lint val)
    {
        if(ql<=l&&r<=qr)
        {
            tag[o]=tr[o]=val;
            return;
        }push_down(o);
        int mid=(l+r)>>1;
        if(mid>=ql)modify(lson,l,mid,ql,qr,val);
        if(mid+1<=qr)modify(rson,mid+1,r,ql,qr,val);
        push_up(o);
    }
    inline lint query(int o,int l,int r,int ql,int qr)
    {
        if(ql<=l&&r<=qr)return tr[o];
        push_down(o);
        int mid=(l+r)>>1;lint res=INF;
        if(mid>=ql)res=min(res,query(lson,l,mid,ql,qr));
        if(mid+1<=qr)res=min(res,query(rson,mid+1,r,ql,qr));
        return res;
    }
    
    #undef lson
    #undef rson 
    inline void addEdge(int u,int v)
    {
        edges[++cnt]=(edge){v,head[u]};
        head[u]=cnt;
    }
    #define cur edges[i].to
    inline void dfs1(int x)
    {
        size[x]=1;
        for(register int i=head[x];i;i=edges[i].nxt)
            if(cur!=fa[x])
            {
                fa[cur]=x;dep[cur]=dep[x]+1;
                dfs1(cur);size[x]+=size[cur];
                if(size[son[x]]<size[cur])son[x]=cur; 
            }
    }
    inline void dfs2(int x,int t)
    {
        top[x]=t;dl[x]=++tot;rk[tot]=x;
        if(son[x])dfs2(son[x],t);
        for(register int i=head[x];i;i=edges[i].nxt)
            if(cur!=fa[x]&&cur!=son[x])dfs2(cur,cur);
        dr[x]=tot;
    }
    #undef cur
    inline void modify_link(int a,int b,int val)
    {
        while(top[a]!=top[b])
        {
            if(dep[top[a]]<dep[top[b]])swap(a,b);
            modify(1,1,n,dl[top[a]],dl[a],val);
            a=fa[top[a]];
        }
        if(dep[a]>dep[b])swap(a,b);
        modify(1,1,n,dl[a],dl[b],val);
    }
    inline lint query_tree(int x)
    {
        if(rot==x)return query(1,1,n,1,n);
        if(dl[x]<=dl[rot]&&dl[rot]<=dr[x])
        {
            int y;
            for(register int i=head[x];i;i=edges[i].nxt)
                if(dl[edges[i].to]<=dl[rot]&&dl[rot]<=dr[edges[i].to])
                {
                    y=edges[i].to;
                    break;
                }
            return min(query(1,1,n,1,dl[y]-1),query(1,1,n,dr[y]+1,n));
        }else
        {
            return query(1,1,n,dl[x],dr[x]);
        }
    }
    int main()
    {
        n=read();m=read();rot=1;
        for(register int i=1;i<n;i++)
        {
            int u,v;u=read();v=read();
            addEdge(u,v);addEdge(v,u);
        }
        for(register int i=1;i<=n;i++)v[i]=read();
        rot=read();
        dfs1(1);dfs2(1,1);build(1,1,n);
        for(register int i=1;i<=m;i++)
        {
            int op,x,y,val;op=read();
            if(op==1)
            {
                rot=read();
            }else if(op==2)
            {
                x=read();y=read();val=read();
                modify_link(x,y,val);
            }else
            {
                x=read();
                printf("%lld
    ",query_tree(x));
            }
        }
    }
  • 相关阅读:
    Systemverilog for design 笔记(三)
    SystemVerilog for design 笔记(二)
    Systemverilog for design 笔记(一)
    假如m是奇数,且m>=3,证明m(m² -1)能被8整除
    SharpSvn操作 -- 获取Commit节点列表
    GetRelativePath获取相对路径
    Dictionary(支持 XML 序列化),注意C#中原生的Dictionary类是无法进行Xml序列化的
    Winform中Checkbox与其他集合列表类型之间进行关联
    Image(支持 XML 序列化),注意C#中原生的Image类是无法进行Xml序列化的
    修复使用<code>XmlDocument</code>加载含有DOCTYPE的Xml时,加载后增加“[]”字符的错误
  • 原文地址:https://www.cnblogs.com/yoshinow2001/p/8320381.html
Copyright © 2011-2022 走看看