zoukankan      html  css  js  c++  java
  • BZOJ3252: 攻略

    题目大意:

    一棵有根的有点权的树。

    每次可以取某个叶子结点到根的路径的点权和。

    并把取过的清0.可以取k次,求取到的最大权值。

    题解:

    贪心+dfs序+线段树

    明显每次取叶子到根的路径权值和最大的,

    把叶子节点到根的权值建在线段树上。

    每次把路径上节点清0。

    假如把p节点清0,在p子树中的叶子节点的sum都会

    减去这个节点的值。

    sum为根到这个叶子结点的权值和。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 200009
    #define LL long long
    using namespace std;
    
    int n,k;
    
    int sumedge,head[N],b[N];
    
    int cnt,re[N],l[N],r[N],dad[N],vis[N];
    
    LL ans,a[N],w[N];
    
    inline int read(){
        char ch=getchar();int x=0,f=1;
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[N];
    
    struct Tree{
        int l,r,p;
        LL mx,s;
    }tr[N<<2];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void dfs(int x,LL sum){
        bool flag=true;l[x]=cnt+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;w[v]+=w[x];flag=false;
            dfs(v,w[v]);
        }
        if(flag)a[++cnt]=sum,re[cnt]=x;
        r[x]=cnt;
    }
    
    void pushup(int rt){
        tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx);
        tr[rt].p=tr[rt<<1].mx>tr[rt<<1|1].mx?tr[rt<<1].p:tr[rt<<1|1].p;
        return;
    }
    
    void pushdown(int rt){
        if(tr[rt].s==0)return;
        tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s;
        tr[rt<<1].mx-=tr[rt].s;tr[rt<<1|1].mx-=tr[rt].s;
        tr[rt].s=0;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].mx=a[l];
            tr[rt].p=l;
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void change(int rt,int l,int r,int ql,int qr,int p){
        if(l>=ql&&r<=qr){
            tr[rt].mx-=p;
            tr[rt].s+=p;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr,p);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p);
        pushup(rt);
    }
    
    int main(){
        n=read();k=read();
        for(int i=1;i<=n;i++)w[i]=read(),b[i]=w[i];
        for(int i=1;i<n;i++){
            int x,y;
            x=read();y=read(); 
            add(x,y);                              
        }
        dfs(1,w[1]);                               
        build(1,1,cnt);                             
        for(int i=1;i<=k;i++){
            LL t=tr[1].mx;int p=tr[1].p;          
            if(t<=0)break;ans+=t;                 
            p=re[p];                              
            while(p&&vis[p]==0){                   
                vis[p]=true;                       
                change(1,1,cnt,l[p],r[p],b[p]);    
                p=dad[p];                         
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    AC
  • 相关阅读:
    changing a pointer rather than erasing memory cells
    验证码识别 edge enhancement 轮廓增强 region finding 区域查找
    Manipulating Data Structures
    passing parameters by value is inefficient when the parameters represent large blocks of data
    Aliasing 走样
    Artificial Intelligence Research Methodologies 人工智能研究方法
    Thread safety
    include pointers as a primitive data type
    flat file
    functional cohesion
  • 原文地址:https://www.cnblogs.com/zzyh/p/7774057.html
Copyright © 2011-2022 走看看