堆
二叉堆
一个小顶堆和一个大顶堆 擅长处理第k个大/小的题目 特点:小堆的数据全都大于大堆的数据 ,保持单调性 。 小堆相当于一个寄存器,每次放数据到小堆后,要保证放一个大顶堆回来!确保大堆数量始终与要求区间长度一致 。
例题
黑匣子: 注意:为了保持单调性,小堆的数据及时拿回来大堆。新来的数据加入大堆可能破坏这种关系。
for ( int i = 1 ; i <= m; i++ ) { q1. push ( a[ i] ) ; while ( i == u[ utop] ) { while ( q1. size ( ) > utop) { q2. push ( q1. top ( ) ) ; q1. pop ( ) ; } cout << q1. top ( ) << endl; if ( ! q2. empty ( ) ) { q1. push ( q2. top ( ) ) ; q2. pop ( ) ; } utop++ ; } }
for ( int i = 1 ; i <= n; i++ ) { cin >> a[ i] ; bq. push ( a[ i] ) ; if ( ( i + 1 ) % 2 == 0 ) { int mid = ( i + 1 ) / 2 ; while ( bq. size ( ) > mid) { sq. push ( bq. top ( ) ) ; bq. pop ( ) ; } cout << bq. top ( ) << endl; if ( ! sq. empty ( ) ) { bq. push ( sq. top ( ) ) ; sq. pop ( ) ; } } }
k叉哈夫曼树 。注意到深度最浅的时候一定是只存在度为0(叶子节点)和度为k的节点(满节点) 。另外最深处可以换一种思路,补充节点,而不是一开始固定合并几个节点。 利用树的性质 :结点数=总度+1->叶子节点数=(k-1)满节点+1,进而确定补充的节点。
# include <bits/stdc++.h>
# define MAX_VALUE 1000009
# define mod 1000007
using ll = long long ;
using namespace std;
int n, k, res;
ll w, ans, max_depth = 0 ;
typedef struct node { ll val; ll depth; node ( ll a, ll b) : val ( a) , depth ( b) { } ;
} ;
class cmp {
public : bool operator ( ) ( const node& a, const node& b) { if ( a. val != b. val) { return a. val > b. val; } else { return a. depth > b. depth; } }
} ;
priority_queue< node, vector< node> , cmp> q; void printout ( ) { while ( ! q. empty ( ) ) { cout << q. top ( ) . val << " " << q. top ( ) . depth << endl; q. pop ( ) ; }
} void solve ( ) { cin >> n >> k; for ( int i = 1 ; i <= n; i++ ) { cin >> w; q. push ( node ( w, 0 ) ) ; } while ( ( n- 1 ) % ( k- 1 ) != 0 ) { q. push ( node ( 0 , 0 ) ) ; n++ ; } while ( ! q. empty ( ) ) { if ( q. size ( ) == 1 ) { cout << ans << endl << max_depth; return ; } ll sum = 0 , new_depth = INT_MIN; for ( int i = 1 ; i <= k; i++ ) { sum += q. top ( ) . val; new_depth = max ( new_depth, q. top ( ) . depth+ 1 ) ; q. pop ( ) ; } ans += sum; max_depth = max ( max_depth, new_depth) ; q. push ( node ( sum, new_depth) ) ; }
} int main ( ) { std:: ios:: sync_with_stdio ( false ) ; std:: cin. tie ( 0 ) ; std:: cout. tie ( 0 ) ; solve ( ) ; return 0 ;
}