1. 问题
给出n个数,求出最优前缀码
2. 解析
每次选出两个数,将两个数合并成一个数,查剩下的有序数组,每一次减少一个数,最后的数就是答案
3. 设计
我们可以使用权值线段树,来实现O(logn)的插入以及O(logn)的删除,当然我们也可以使用链表等手段,这里我使用了multiset的c++容器来实现插入与删除;
1 for(int i=1;i<=n-1;i++){ 2 int x=*s.begin(); 3 s.erase(s.begin()); 4 int y=*s.begin(); 5 s.erase(s.begin()); 6 s.insert(x+y); 7 }
4. 分析
O(nlogn)
5. 源码
https://github.com/Tinkerllt/algorithm-work.git
1 #include<stdio.h> 2 #include<cstdio> 3 #include<iostream> 4 #include<cmath> 5 #include<cstring> 6 #include<algorithm> 7 #include<bitset> 8 #include<set> 9 #include<deque> 10 #include<queue> 11 #include<vector> 12 //#include<unordered_map> 13 #include<map> 14 #include<stack> 15 using namespace std; 16 #define ll long long 17 #define ull unsigned long long 18 #define pii pair<int,int> 19 #define Pii pair<ll,int> 20 #define m_p make_pair 21 #define l_b lower_bound 22 #define u_b upper_bound 23 const int inf = 0x3f3f3f3f; 24 const ll linf = 0x3f3f3f3f3f3f3f3f; 25 const int maxn = 2e6 + 11; 26 const int maxm = 600 + 11; 27 const int mod = 1e9 + 7; 28 const double eps = 1e-5; 29 inline ll rd() { ll x = 0, f = 1; char ch = getchar(); while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }return x * f; } 30 inline ll qpow(ll a, ll b, ll p) { ll res = 1; while (b) { if (b & 1) { res *= a; res %= p; }b >>= 1; a = a * a%p; }return res; } 31 inline ll gcd(ll a, ll b) { if (b == 0) return a; return gcd(b, a%b); } 32 //iterator 33 //head 34 //priority_queue 35 multiset<int>s; 36 int main() { 37 int n=rd(); 38 for(int i=1;i<=n;i++){ 39 int x=rd(); 40 s.insert(x); 41 } 42 for(int i=1;i<=n-1;i++){ 43 int x=*s.begin(); 44 s.erase(s.begin()); 45 int y=*s.begin(); 46 s.erase(s.begin()); 47 s.insert(x+y); 48 } 49 printf("%d ",*s.begin()); 50 }