题目来源: 洛谷P1090 合并果子
一维数组做法
本题是一个简单的 Huffman树。Huffman编码 在 UTF-8 & Unicode 中都有它思想的体现,即出现频率高的编码长度短,出现频率低的编码长度长,用以缩短整体编码长度
这里我也运用了前面 P1309 的思想:因为每次需要重新排序的时候只有一个数据需要被插入整个数列当中,所以并不需要假定数据无序的 quick sort,反而是线性的排序更快
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int main() { int n,berry[10005];long long ans=0; cin>>n; for(int i=1;i<=n;i++) cin>>berry[i];
sort(berry+1,berry+1+n);
for(int i=1;i<=n-1;i++){ berry[i+1]=berry[i]+berry[i+1]; ans+=berry[i+1]; if(berry[i+1]>berry[i+2]){ for(int j=i+1;j<=n-1;j++){ if(berry[j]>berry[j+1]) swap(berry[j],berry[j+1]); } } }
cout<<ans;
return 0; }
|
据说是离散化算法 就是先把原本的从小到大排序排好。然后用两个队列,一个是存储原本的,另一个是存储合成的(由于原本的是从小到大所有新开的也是从小到大)。然后在两个队列的头取最小的,执行两次然后把这两个合并加入第二个队列中。 然后由于输入: (1≤ai≤20000)(1≤ai≤20000)(1≤ai≤20000) ,所以用桶排序就可以 O(n)O(n)O(n) 时间复杂度
要义是储存原本果堆的a1是按顺序排列的,所以存储两两合成的新果堆的a2也是按顺序排列的。取这两个果堆序列中最小的两个果堆,必定获得这一步能获得的最小的果堆。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int k,x,num,n1,n2,a1[30001],a2[30001],t[20001],w,sum; int main() { scanf("%d",&num); memset(a1,127/3,sizeof(a1)); memset(a2,127/3,sizeof(a2)); for (int i=1;i<=num;i++) { scanf("%d",&x); t[x]++; } for (int i=1;i<=20000;i++) { while (t[i]) { t[i]--; a1[++n1]=i; } } int i=1,j=1; k=1; while (k<num) { if (a1[i]<a2[j]) { w=a1[i]; i++; } else { w=a2[j]; j++; } if (a1[i]<a2[j]) { w+=a1[i]; i++; } else { w+=a2[j]; j++; } a2[++n2]=w; k++; sum+=w; } printf("%d",sum); }
|
s 代表 son, p 代表 parent, size 代表整个二叉堆中存储的数据数量
完美二叉树, 完全二叉树和完满二叉树的区分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include<bits/stdc++.h> using namespace std; const int maxn=10000+10; int n,heap[maxn],size=0; void up(int p) { while(p>1) { if(heap[p]<heap[p/2]) { swap(heap[p],heap[p/2]); p/=2; } else break; } } void insert(int val) { heap[++size]=val; up(size); } void down(int p) { int s=p*2; while(s<=size) { if(s<size&&heap[s+1]<heap[s]) s++; if(heap[s]<heap[p]) { swap(heap[s],heap[p]); p=s; s=p*2; } else break; } } void extract() { heap[1]=heap[size--]; down(1); } int gettop() { return heap[1]; } int main() { cin>>n; for(int i=1; i<=n; i++) { int a; cin>>a; insert(a); } long long ans=0; while(size>=2) { int top1=gettop(); extract(); int top2=gettop(); extract(); ans+=(top1+top2); insert(top1+top2); } cout<<ans<<endl; return 0; }
|