zoukankan      html  css  js  c++  java
  • luogu P5290 [十二省联考2019]春节十二响

    传送门

    做题千万条,读题第一条
    编程不规范,爆零两行泪

    推荐阅读(雾)

    考虑一个贪心,就是先把所有点按权值从大到小排序,然后每次考虑能不能和其他已经插进去的点放在一个集合,不能那么答案就加上对应权值.如果我们按照最优策略构造,那么最后首先集合个数是最少的,而且因为尽量把大的元素和更大的放在一起,那么最终答案也是最优的

    这个贪心怎么优化呢?注意到两个点可以在一起选,当且仅当这两个点的子树的(dfn)序区间无交,那么每次选点的过程中,如果所有集合都和他无交,那么可以放在其他集合中,否则就必须新开一个集合.那如果加一个点就在对应区间+1,考虑当前这个区间的最大值,他代表有几个集合和当前区间有交,所以如果区间最大值为当前集合个数就要新开一个集合,那么要更新答案.这个可以线段树区间加,区间最大值实现

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    #define db double
    
    using namespace std;
    const int N=2e5+10;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int to[N<<1],nt[N<<1],hd[N],tot=1;
    void add(int x,int y)
    {
        ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
    }
    int n,a[N],dfn[N],ti,sz[N];
    void dfs(int x)
    {
        sz[x]=1,dfn[x]=++ti;
        for(int i=hd[x];i;i=nt[i])
        {
            int y=to[i];
            dfs(y),sz[x]+=sz[y];
        }
    }
    struct node
    {
        int l,r,x;
        bool operator < (const node &bb) const {return x>bb.x;}
    }qq[N];
    int ma[N<<2],tg[N<<2];
    #define mid ((l+r)>>1)
    void psup(int o){ma[o]=max(ma[o<<1],ma[o<<1|1]);}
    void ad(int o,int x){ma[o]+=x,tg[o]+=x;}
    void psdn(int o){if(tg[o]) ad(o<<1,tg[o]),ad(o<<1|1,tg[o]),tg[o]=0;}
    void modif(int o,int l,int r,int ll,int rr)
    {
        if(ll<=l&&r<=rr){ad(o,1);return;}
        psdn(o);
        if(ll<=mid) modif(o<<1,l,mid,ll,rr);
        if(rr>mid) modif(o<<1|1,mid+1,r,ll,rr);
        psup(o);
    }
    int quer(int o,int l,int r,int ll,int rr)
    {
        if(ll<=l&&r<=rr) return ma[o];
        psdn(o);
        int an=0;
        if(ll<=mid) an=max(an,quer(o<<1,l,mid,ll,rr));
        if(rr>mid) an=max(an,quer(o<<1|1,mid+1,r,ll,rr));
        psup(o);
        return an;
    }
    LL cn,ans;
    
    int main()
    {
        n=rd();
        for(int i=1;i<=n;++i) a[i]=rd();
        for(int i=2;i<=n;++i) add(rd(),i);
        dfs(1);
        for(int i=1;i<=n;++i) qq[i]=(node){dfn[i],dfn[i]+sz[i]-1,a[i]};
        sort(qq+1,qq+n+1);
        for(int i=1;i<=n;++i)
        {
            int ll=qq[i].l,rr=qq[i].r;
            if(quer(1,1,n,ll,rr)>=cn) ++cn,ans+=qq[i].x;
            modif(1,1,n,ll,rr);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    ASP.NET 4.0 与 Entity Framework 4第三篇使用Entity Framework调用存储过程
    雕虫无小技 JavaScript初学者的10个迷你技巧
    IE6下button随着文字的增多两边的内容边框也会增加的bug
    bigint ,int ,smallint ,tinyint 数据类型
    分享7个不错的jQuery游戏( 转)
    IE CSS Bug及解决方案参考手册
    利用CSS样式打印
    SQL 2005 弹出不允许对系统目录进行即席更新解决方法
    VS2010快捷键
    SQL2K,DTC错误:"该伙伴事务管理器已经禁止了它对远程/网络事务的支持"的解决办法
  • 原文地址:https://www.cnblogs.com/smyjr/p/10724798.html
Copyright © 2011-2022 走看看