zoukankan      html  css  js  c++  java
  • bzoj3252攻略(线段树+dfs序)

    3252: 攻略

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 562  Solved: 238
    [Submit][Status][Discuss]

    Description

    题目简述:树版[k取方格数]
     
    众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏。
    今天他得到了一款新游戏《XX半岛》,这款游戏有n个场景(scene),某些场景可以通过不同的选择支到达其他场景。所有场景和选择支构成树状结构:开始游戏时在根节点(共通线),叶子节点为结局。每个场景有一个价值,现在桂马开启攻略之神模式,同时攻略k次该游戏,问他观赏到的场景的价值和最大是多少(同一场景观看多次是不能重复得到价值的)
    “为什么你还没玩就知道每个场景的价值呢?”
    “我已经看到结局了。”

    Input

    第一行两个正整数n,k
    第二行n个正整数,表示每个场景的价值
    以下n-1行,每行2个整数a,b,表示a场景有个选择支通向b场景(即a是b的父亲)
    保证场景1为根节点

    Output

     
    输出一个整数表示答案

    Sample Input

    5 2
    4 3 2 1 1
    1 2
    1 5
    2 3
    2 4

    Sample Output

    10

    HINT

     

    对于100%的数据,n<=200000,1<=场景价值<=2^31-1

     

    Source

    dfs序+线段树

    /*
    嗯,需要维护每个点到根的距离。
    首先开始的时候选取叶子结点一定比中间节点优。 
    当选择了一条链的时候,会对哪些点有影响呢?
    答案当然是在这条链上的点的子树。把这个点的子树权值减掉这个点的权值就好。
    看到子树,想到dfs序。又因为要查询最大值,所以可以想到用线段树实现。
    线段树每个节点维护原树每个点到根的距离的最大值和原树每个节点dfs序所对应的点的编号。 
    每次查询区间最大值,然后删去这条链,每次删的时候更新子树权值(区间减法)。
    删除把这个点的权值赋值为0就好。然后往上走,走的时候到某个点权值为0那么就停。
    因为如果某个点权值为0,那么他到根的路径上所有点权都为零。恩。 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define N 200007
    #define ll long long
    
    using namespace std;
    ll n,m,ans,cnt,tot;
    ll head[N],dis[N],fa[N];
    ll S[N],pos[N],T[N],a[N];
    struct edge{
        int u,v,net,w;
    }e[N<<1];
    struct tree{
        ll l,r,mx,pos,flag;
    }tr[N<<2];
    
    namespace seg
    {
        void pushup(int k)
        {
            if(tr[k<<1].mx>tr[k<<1|1].mx) tr[k].mx=tr[k<<1].mx,tr[k].pos=tr[k<<1].pos;
            else tr[k].mx=tr[k<<1|1].mx,tr[k].pos=tr[k<<1|1].pos;
        }
        void pushdown(int k)
        {
            tr[k<<1].flag+=tr[k].flag;tr[k<<1|1].flag+=tr[k].flag;
            tr[k<<1].mx+=tr[k].flag;tr[k<<1|1].mx+=tr[k].flag;
            tr[k].flag=0;
        }
        void build(int k,int l,int r)
        {
            tr[k].l=l;tr[k].r=r;
            if(l==r) 
            {
                tr[k].mx=dis[pos[l]],tr[k].pos=pos[l];
                return;
            }
            int mid=l+r>>1;
            build(k<<1,l,mid);build(k<<1|1,mid+1,r);
            pushup(k);
        }
        void update(int k,int l,int r,int z)
        {
            if(tr[k].l==l && tr[k].r==r) 
            {
                tr[k].mx+=z;tr[k].flag+=z;
                return;
            }
            pushdown(k);
            int mid=tr[k].l+tr[k].r>>1;
            if(r<=mid) update(k<<1,l,r,z);
            else if(l>mid) update(k<<1|1,l,r,z);
            else update(k<<1,l,mid,z),update(k<<1|1,mid+1,r,z);
            pushup(k);
        }
    
    }using namespace seg;
    
    inline void add(int u,int v)
    {
        e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
    }
    
    inline ll read()
    {
        ll x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    void dfs(int u,int last,ll sum)
    {
        S[u]=++tot;pos[tot]=u;dis[u]=sum;
        for(int i=head[u];i;i=e[i].net)
        {
            int v=e[i].v;
            if(v==last) continue;
            fa[v]=u;dfs(v,u,sum+a[v]);
        }T[u]=tot;
    }
    
    void change(int u)
    {
        while(a[u])
        {
            update(1,S[u],T[u],-a[u]);
            a[u]=0;u=fa[u];
        }
    }
    
    int main()
    {
        int x,y;
        n=read();m=read();
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<n;i++) 
        {
            x=read();y=read();
            add(x,y);add(y,x);
        }ans=a[1];a[1]=0;dfs(1,0,0);
        build(1,1,n);
        while(m--)
        {
            tree Tr=tr[1];ans+=Tr.mx;
            change(Tr.pos);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    Python语言基础03-分支和循环结构
    Python语言基础01-初识Python
    李宏毅深度学习笔记08---Bert、ELMO、GPT
    李宏毅深度学习笔记07---Transformer
    李宏毅深度学习笔记06---word embedding(词嵌入也称词向量)
    李宏毅深度学习笔记05---RNN 循环神经网络02
    李宏毅深度学习笔记04---RNN 循环神经网络01
    李宏毅深度学习笔记03---CNN 卷积神经网络
    李宏毅深度学习笔记02---深度学习的发展历程、3大研究步骤、
    李宏毅深度学习笔记---课程介绍
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7756865.html
Copyright © 2011-2022 走看看