zoukankan      html  css  js  c++  java
  • BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description

    描述
    zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

    问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

    Input

    第1行两个整数n m,代表城市个数和操作数。
    第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。
    第n+1行,有n个整数,代表所有点的初始防御值。
    第n+2行一个整数 id,代表初始的首都为id。
    第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。

    Output


    对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

    Sample Input

    3 7

    1 2

    1 3

    1 2 3

    1

    3 1

    2 1 1 6

    3 1

    2 2 2 5

    3 1

    2 3 3 4

    3 1

    Sample Output

    1

    2

    3

    4

    提示

    对于20%的数据,n<=1000 m<=1000。

    对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。

    对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。

    对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。

    对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。

    题解:首先看到路径修改和子树查询,树链剖分就没得跑了,当然也可以写LCT

    操作2/3用树剖自然好写,难的是一,换根怎么看怎么尬

    想了一想,如果根就是询问点,子树就是整个区间

    如果根在祖先,该点的子树不变.仍是按照正规的树剖查法查

    如果根在询问点的任何一个子树中,那么该询问点的子树就变成了除了这个子树之外的所有区间.

    主要是如何确定这个根在哪个子树中比较麻烦,写一个类似lca的玩意,倍增记录他的祖先,到时候一点点跳上去,复杂度还是可以接受的.

    我一直以为是线段树写错了,果然做题太少了orz

    代码如下:

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lson root<<1
    #define rson root<<1|1
    #define inf 0x3f3f3f3f
    using namespace std;
    
    struct node
    {
        int lazy,m,l,r;
    } tr[400040];
    int n,deep[100010],son[100010],fa[100010],size[100010],id[100010],top[100010],c[100010],w[100010],cnt,rt;
    vector<int> g[100010];
    
    void push_up(int root)
    {
        tr[root].m=min(tr[lson].m,tr[rson].m);
    }
    
    void push_down(int root)
    {
        tr[lson].m=tr[root].lazy;
        tr[lson].lazy=tr[root].lazy;
        tr[rson].m=tr[root].lazy;
        tr[rson].lazy=tr[root].lazy;
        tr[root].lazy=inf;
    }
    
    void build(int root,int l,int r)
    {
        if(l==r)
        {
            tr[root].l=l;
            tr[root].r=r;
            tr[root].lazy=inf;
            tr[root].m=w[l];
            return ;
        }
        int mid=(l+r)>>1;
        tr[root].l=l;
        tr[root].r=r;
        tr[root].lazy=inf;
        build(lson,l,mid);
        build(rson,mid+1,r);
        push_up(root);
    }
    
    void update(int root,int l,int r,int val)
    {
        if(l==tr[root].l&&r==tr[root].r)
        {
            tr[root].lazy=val;
            tr[root].m=val;
            return ;
        }
        int mid=(tr[root].l+tr[root].r)>>1;
        if(tr[root].lazy!=inf)
        {
            push_down(root);
        }
        if(l>mid)
        {
            update(rson,l,r,val);
        }
        else
        {
            if(r<=mid)
            {
                update(lson,l,r,val);
            }
            else
            {
                update(lson,l,mid,val);
                update(rson,mid+1,r,val);
            }
        }
        push_up(root);
    }
    
    int query(int root,int l,int r)
    {
        if(l>r)
        {
            return inf;
        }
        if(tr[root].l==l&&tr[root].r==r)
        {
            return tr[root].m;
        }
        int mid=(tr[root].l+tr[root].r)>>1;
        if(tr[root].lazy!=inf)
        {
            push_down(root);
        }
        if(l>mid)
        {
            return query(rson,l,r);
        }
        else
        {
            if(r<=mid)
            {
                return query(lson,l,r);
            }
        }
        return min(query(lson,l,mid),query(rson,mid+1,r));
    }
    
    void dfs1(int now,int f,int dep)
    {
        deep[now]=dep;
        fa[now]=f;
        size[now]=1;
        int maxson=-1;
        for(int i=0; i<g[now].size(); i++)
        {
            if(g[now][i]==f)
            {
                continue;
            } 
            dfs1(g[now][i],now,dep+1);
            size[now]+=size[g[now][i]];
            if(size[g[now][i]]>maxson)
            {
                son[now]=g[now][i];
                maxson=size[g[now][i]];
            }
        }
    }
    
    void dfs2(int now,int topf)
    {
        id[now]=++cnt;
        w[cnt]=c[now];
        top[now]=topf;
        if(!son[now])
        {
            return ;
        }
        dfs2(son[now],topf);
        for(int i=0; i<g[now].size(); i++)
        {
            if(g[now][i]==fa[now]||g[now][i]==son[now])
            {
                continue;
            }
            dfs2(g[now][i],g[now][i]);
        }
    }
    
    void path_update(int x,int y,int val)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])
            {
                swap(x,y);
            }
            update(1,id[top[x]],id[x],val);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])
        {
            swap(x,y);
        }
        update(1,id[x],id[y],val);
    }
    
    int sub_query(int x)
    {
        if(x==rt)
        {
            return query(1,1,cnt);
        }
        if(id[rt]<=id[x]+size[x]-1&&id[rt]>=id[x])
        {
            return min(query(1,1,id[x]-1),query(1,id[x]+size[x],cnt));
        }
        return query(1,id[x],id[x]+size[x]-1);
    }
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n-1;i++)
        {
            int from,to;
            scanf("%d%d",&from,&to);
            g[from].push_back(to);
            g[to].push_back(from);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&c[i]);
        }
        scanf("%d",&rt);
        dfs1(rt,0,1);
        dfs2(rt,rt);
        build(1,1,n);
        int kd,ll,rr,vv;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&kd);
            if(kd==1)
            {
                scanf("%d",&vv);
                rt=vv;
            }
            if(kd==2)
            {
                scanf("%d%d%d",&ll,&rr,&vv);
                path_update(ll,rr,vv);
            }
            if(kd==3)
            {
                scanf("%d",&vv);
                printf("%d
    ",sub_query(vv));
            }
        }
    }
  • 相关阅读:
    asp.net mvc 从数据库中读取图片
    给折腾ramdisk的朋友们一点建议
    docker安装Jenkins和构建python容器
    docker笔记
    接口加密方式
    Dockerfile常用命令
    北斗七星小队团队展示
    固件程序设计实验内容1.4
    Myod实验 20181328祝维卿
    电子公文系统团队作业(四):描述设计
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/8654585.html
Copyright © 2011-2022 走看看