BZOJ3083 遥远的国度

Posted zcdhj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3083 遥远的国度相关的知识,希望对你有一定的参考价值。

BZOJ

可以发现,如果每次换根操作都重新跑一遍树剖是会T到死的。

因为树的形态不变,考虑分类讨论一下换根操作对答案的影响。

如果当前根等于\(X\)则直接输出整个树的最小值。

如果\(LCA(X,root)≠X\),对答案没有任何影响,直接查询。

如果\(LCA(X,root)=x\),发现除了以从\(X\)\(root\)的最近的那个点为根的子树,其他都是\(X\)的子孙,因为一颗子树内的\(dfn\)都是连续的,直接在查询的时候把这个区间筛掉即可。

#include <bits/stdc++.h>

#define lson (o<<1)
#define rson (o<<1|1)
#define mid (l+r>>1)

typedef long long ll;

const int max_n=100000+5;
const int inf=2147483647;

int N,M,root,cnt,tot;
int size[max_n],top[max_n],son[max_n],father[max_n],depth[max_n],dfn[max_n],first_edge[max_n];

ll wt[max_n],W[max_n];

struct Segment_tree
{
    ll minv,lazy;
    Segment_tree()
    {
        minv=lazy=0;
    }
}tree[max_n<<2];

struct Edge
{
    int to,next_edge;
}edge[max_n<<1];

inline int read()
{
    register ll x=0;
    register char ch=getchar();
    while(!isdigit(ch))
        ch=getchar();
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+ch-‘0‘;
        ch=getchar();
    }
    return x;
}

inline void add_edge(int x,int y)
{
    edge[++tot].to=y;
    edge[tot].next_edge=first_edge[x];
    first_edge[x]=tot;
}

inline void push_up(int o)
{
    tree[o].minv=std::min(tree[lson].minv,tree[rson].minv);
}

inline void push_down(int o)
{
    if(tree[o].lazy)
    {
        tree[lson].lazy=tree[rson].lazy=tree[o].lazy;
        tree[lson].minv=tree[rson].minv=tree[o].lazy;
        tree[o].lazy=0;
    }
}

void build(int o,int l,int r)
{
    if(l==r)
    {
        tree[o].minv=wt[l];
        return;
    }
    build(lson,l,mid),build(rson,mid+1,r);
    push_up(o);
}

void update(int o,int l,int r,int ql,int qr,int v)
{
    if(ql<=l && r<=qr)
    {
        tree[o].minv=tree[o].lazy=v;
        return;
    }
    push_down(o);
    if(ql<=mid) update(lson,l,mid,ql,qr,v);
    if(mid<qr) update(rson,mid+1,r,ql,qr,v);
    push_up(o);
}

int query(int o,int l,int r,int ql,int qr)
{
    if(ql<=l && r<=qr) return tree[o].minv;
    int res=inf;
    push_down(o);
    if(ql<=mid) res=query(lson,l,mid,ql,qr);
    if(mid<qr) res=std::min(res,query(rson,mid+1,r,ql,qr));
    return res;
}

void dfs1(int x,int fa)
{
    depth[x]=depth[fa]+1;
    father[x]=fa;
    size[x]=1;
    int maxx=-1;
    for(int k=first_edge[x];k;k=edge[k].next_edge)
    {
        if(edge[k].to!=fa)
        {
            dfs1(edge[k].to,x);
            size[x]+=size[edge[k].to];
            if(size[edge[k].to]>maxx)
            {
                maxx=size[edge[k].to];
                son[x]=edge[k].to;
            } 
        }
    }
}

void dfs2(int x,int topf)
{
    dfn[x]=++cnt;
    wt[cnt]=W[x];
    top[x]=topf;
    if(!son[x]) return;
    dfs2(son[x],topf);
    for(int k=first_edge[x];k;k=edge[k].next_edge)
        if(edge[k].to!=father[x] && edge[k].to!=son[x]) dfs2(edge[k].to,edge[k].to);
}

int LCA(int x,int y)
{
    while(top[x]^top[y])
    {
        if(depth[top[x]]<depth[top[y]]) std::swap(x,y);
        x=father[top[x]];
    }
    return (depth[x]<depth[y])?x:y;
}

void modify(int x,int y,int z)
{
    while(top[x]^top[y])
    {
        if(depth[top[x]]<depth[top[y]]) std::swap(x,y);
        update(1,1,N,dfn[top[x]],dfn[x],z);
        x=father[top[x]];
    }
    if(depth[x]>depth[y]) std::swap(x,y);
    update(1,1,N,dfn[x],dfn[y],z);
}

ll calc(int x)
{
    if(x==root) return query(1,1,N,1,size[1]);
    else if(LCA(x,root)!=x) return query(1,1,N,dfn[x],dfn[x]+size[x]-1);
    else
    {
        int k=root;
        while(father[k]!=x)
            k=father[k];
        return std::min(query(1,1,N,1,dfn[k]-1),query(1,1,N,dfn[k]+size[k],N));
    }
}

int main()
{
    int opt,x,y,z;
    N=read(),M=read();
    for(int i=1;i<N;++i)
    {
        x=read(),y=read();
        add_edge(x,y),add_edge(y,x);
    }
    for(int i=1;i<=N;++i)
        W[i]=read();
    root=read();
    dfs1(root,0),dfs2(root,root);
    build(1,1,N);
    for(int i=1;i<=M;++i)
    {
        opt=read();
        if(opt==1) root=read();
        else if(opt==2)
        {
            x=read(),y=read(),z=read();
            modify(x,y,z);
        }
        else printf("%lld\n",calc(read()));
    }
    return 0;
}

以上是关于BZOJ3083 遥远的国度的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3083: 遥远的国度

BZOJ 3083 遥远的国度(树链剖分+LCA)

bzoj3083遥远的国度(树链剖分+线段树)

遥远的国度 bzoj3083

BZOJ3083: 遥远的国度

BZOJ 3083 遥远的国度