• luogu P5290 [十二省联考2019]春节十二响 优先队列 + 启发式合并


    思维难度不大,在考上上写的启发式合并写错了,只拿了 60 pts,好难过QAQ

    没什么太难的,在考场上想出链的部分分之后很容易就能想到正解.
    没错,就是非常短的启发式合并.
    注意一下,写的要漂亮一点,否则会疯狂 TLE.
    还有一个细节,想交换优先队列时不能直接交换队列,而是对于树中每个节点都存一个在实际队列编号中的位置,计为 $idx[u]$,每次交换 $idx[u]$ 和 $idx[to[v]]$.

    Code:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <set>
    #include <queue> 
    #define maxn 200001  
    #define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) 
    using namespace std; 
    priority_queue<int>Q[maxn];    
    int edges; 
    int n; 
    int head[maxn],to[maxn],nex[maxn],val[maxn],f[maxn]; 
    void addedge(int u,int v){
    	nex[++edges] = head[u], head[u] = edges, to[edges] = v; 
    }
    int tmp[maxn]; 
    int id[maxn]; int idx; 
    void DFS(int u){      
        id[u]=++idx; 
    	for(int v=head[u];v;v=nex[v]){
    		DFS(to[v]); 
    		if(Q[id[u]].size() < Q[id[to[v]]].size()) swap(id[u],id[to[v]]); 
            int m=Q[id[to[v]]].size(); 
            for(int i=1;i<=m;++i) {
                tmp[i]=max(Q[id[u]].top(),Q[id[to[v]]].top()); 
                Q[id[u]].pop(); Q[id[to[v]]].pop(); 
            }
            for(int i=1;i<=m;++i) Q[id[u]].push(tmp[i]); 
    	}
    	Q[id[u]].push(val[u]);              
    }
    int main(){
    	//setIO("spring"); 
    	scanf("%d",&n); 
    	for(int i = 1;i <= n; ++i) scanf("%d",&val[i]); 
    	for(int i = 2;i <= n; ++i) scanf("%d",&f[i]); 
    	for(int i = 2;i <= n; ++i) addedge(f[i],i); 
    	DFS(1); 
    	long long ans = 0; 
    	while(!Q[id[1]].empty())ans += (long long)Q[id[1]].top(), Q[id[1]].pop(); 
    	printf("%lld
    ",ans); 
    	return 0;  
    }
    

      

  • 相关阅读:
    SignalRMvc的简单例子
    CTE递归查询
    数据库表设计(邻接表、路径枚举、嵌套集、闭包表)
    EF事务
    context日志
    Context连接和断开的情况下的CRUD操作
    Sql语句拼接(EXEC和sp_executesql的区别)
    实体框架中的变更跟踪
    sql server 添加字段并且赋默认值和说明
    C# .ToString() 格式化
  • 原文地址:https://www.cnblogs.com/guangheli/p/10672929.html
Copyright © 2020-2023  润新知