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

      考虑贪心,每次选价值最大的链。选完之后对于链上点dfs序暴力修改子树。因为每个点最多被选一次,复杂度非常正确。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 200010
    #define ll long long
    #define inf 1000000000000000
    int n,m,a[N],p[N],fa[N],id[N],dfn[N],size[N],cnt=0,t=0;
    bool isleaf[N],flag[N];
    int L[N<<2],R[N<<2];
    ll deep[N],tree[N<<2],lazy[N<<2],ans;
    struct data{int to,nxt;
    }edge[N];
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void dfs(int k)
    {
        size[k]=1;deep[k]=deep[fa[k]]+a[k];
        id[k]=++cnt;dfn[cnt]=k;
        for (int i=p[k];i;i=edge[i].nxt) 
        if (edge[i].to!=fa[k]) dfs(edge[i].to),size[k]+=size[edge[i].to];
    }
    void up(int k){tree[k]=max(tree[k<<1],tree[k<<1|1]);}
    void down(int k)
    {
        tree[k<<1]+=lazy[k],tree[k<<1|1]+=lazy[k];
        lazy[k<<1]+=lazy[k],lazy[k<<1|1]+=lazy[k];
        lazy[k]=0;
    }
    void build(int k,int l,int r)
    {
        L[k]=l,R[k]=r;
        if (l==r) {tree[k]=isleaf[dfn[l]]?deep[dfn[l]]:-inf;return;}
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        up(k);
    }
    int query(int k)
    {
        if (L[k]==R[k]) return L[k];
        if (lazy[k]) down(k);
        if (tree[k<<1]>tree[k<<1|1]) return query(k<<1);
        else return query(k<<1|1);
    }
    void add(int k,int l,int r,int x)
    {
        if (L[k]==l&&R[k]==r) {tree[k]+=x,lazy[k]+=x;return;}
        if (lazy[k]) down(k);
        int mid=L[k]+R[k]>>1;
        if (r<=mid) add(k<<1,l,r,x);
        else if (l>mid) add(k<<1|1,l,r,x);
        else add(k<<1,l,mid,x),add(k<<1|1,mid+1,r,x);
        up(k);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3252.in","r",stdin);
        freopen("bzoj3252.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++) a[i]=read(),isleaf[i]=1;
        for (int i=1;i<n;i++)
        {
            int x=read(),y=read();
            addedge(x,y);fa[y]=x;isleaf[x]=0;
        }
        dfs(1);
        build(1,1,n);
        flag[0]=1;
        while (m--)
        {
            if (tree[1]<=0) break;
            ans+=tree[1];
            int x=dfn[query(1)];
            while (!flag[x])
            {
                flag[x]=1;
                add(1,id[x],id[x]+size[x]-1,-a[x]);
                x=fa[x];
            }
        } 
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Android画图最基本的三个对象(Color,Paint,Canvas)
    搭建Android开发环境之旅
    对象序列化与反序列化
    JUnit 3.8 演示递归删除文件目录的 测试类程序 .
    JUnit 3.8 让所有测试程序 实现 复合的测试(TestSuite)
    JUnit 3.8 通过反射测试私有方法
    Java NIO
    Java泛型 类型变量的限定
    组织领导层在信息化建设中须要解决的问题
    bootstrap之鼠标操作
  • 原文地址:https://www.cnblogs.com/Gloid/p/9678087.html
Copyright © 2011-2022 走看看