• 题解:2019十二省联考 春节十二响


    这个题目应该算是今年省选最简单的一题了 然而为什么HB就是有wjyyy切了呢

    首先来说一下贪心的思想(考场上应该想出来的人很多)
    由于在同一条链上不能同时选,但是在不同的练上是相互不影响,我们用两个队列来表示
    比如举个例子(就是一条链的情况吧)
    我们把1的两个儿子底下的一整条链先求出来,然后排个序(由于考虑到同一条链不能同时选,所以内部的顺序并不影响)
    假如排完了是这样的情况:

    \[a:10,8,6,4,2,1 \]

    \[b: 9,7,7,5 \]

    我们来看怎么贪心,如果把10和9放在一起,那么只会产生10的影响,否则一共会产生10+9的影响,也就是说,只有和10一起才能消掉9,于是我们的操作就是把10加进答案,然后弹出9,10,同样,8加进答案,弹出7,8,就这样,最后剩下的数1,2单独加入
    于是这样就是一个贪心,于是链的15分(复杂度\(NlogN\))

    同样,结合这个贪心,我们可以拓展到整棵树上,用优先队列进行维护,复杂度\(N^2logN\),得分60

    然而,如果使用启发式合并,由于每次操作只会弹两个,进一次,所以复杂度就是\(NlogN\),于是就可以有好的切掉了

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    using namespace std;
    
    #define re register
    #define ll long long
    #define gc getchar()
    inline int read()
    {
     	re int x(0),f(1);re char c(gc);
        while(c>'9'||c<'0')f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9')x=x*10+c-48,c=gc;
        return f*x;
    }
    
    const int N=1100000;
    struct node{int to,next;}e[N];
    int h[N],cnt,tot,n,po[N];
    ll ans,val[N],now[N];
    priority_queue<ll> son[N];
    void add(int x,int y){e[++cnt]=(node){y,h[x]};h[x]=cnt;} 
    #define QXX(u) for(int i=h[u],v;v=e[i].to,i;i=e[i].next)
    
    void dfs(int u)
    {
        po[u]=u;
     	QXX(u)
        {
            dfs(v);
         	if(i==h[u])	po[u]=po[v];
            else
            {
             	if(son[po[u]].size()<son[po[v]].size())
                    swap(po[u],po[v]);
                tot=0;
                while(!son[po[v]].empty())
                {
                    now[++tot]=max(son[po[v]].top(),son[po[u]].top());
                    son[po[u]].pop();
                    son[po[v]].pop();
                }
                for(int j=1;j<=tot;j++)
                    son[po[u]].push(now[j]);
            } 
        }
        son[po[u]].push(val[u]);
    } 
    int main()
    {
        n=read();
        for(re int i=1;i<=n;i++)
            val[i]=read();
        for(re int i=2;i<=n;i++)
        {
         	int fa=read();
             add(fa,i);
        } 
        dfs(1);
        while(!son[po[1]].empty())
            ans+=son[po[1]].top(),son[po[1]].pop();
        cout<<ans;
        return 0;
    } 
    
  • 相关阅读:
    迷宫最短路径问题的dfs,bfs实现
    高效率的排序算法2--归并排序
    高效率的排序算法1--快速排序
    POJ No.2386 Lake Counting
    部分和问题 --dfs
    dfs的一个小实现(啊哈算法的例题)
    HDU 5710 Digit Sum
    【视频播放器】在macOS上使用IINA
    视音频格式基础知识&视频压缩
    影视作品(电影,电视剧,PV,MAD,AMV)的制作程序
  • 原文地址:https://www.cnblogs.com/zijinjun/p/10694784.html
Copyright © 2020-2023  润新知