// 交换两个点,及其映射关系 voidheap_swap(int a, int b) { swap(ph[hp[a]],ph[hp[b]]); swap(hp[a], hp[b]); swap(h[a], h[b]); }
voiddown(int u) { int t = u; if (u * 2 <= size && h[u * 2] < h[t]) t = u * 2; if (u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1; if (u != t) { heap_swap(u, t); down(t); } }
voidup(int u) { while (u / 2 && h[u] < h[u / 2]) { heap_swap(u, u / 2); u >>= 1; } }
// O(n)建堆 for (int i = n / 2; i; i -- ) down(i);
//java代码几个关键的 publicstaticvoiddown(int i){ int min = i; int l = 2*i; int r = 2*i+1; if(l<=n && heap[l]<heap[min]){ min = l; } if(r <=n && heap[r]<heap[min]){ min = r; } if(min!=i){ int temp = heap[min]; heap[min] = heap[i]; heap[i] = temp; //记得递归down down(min); } }
//初始化 for(int i=n/2;i>0;i--){ down(i); }
题目
AcWing
838 堆排序
839 模拟堆
Ac839 堆排序
描述
输入一个长度为n的整数数列,从小到大输出前m小的数。
解答
import java.io.*;
publicclassMain{ staticfinalint N = 100010; staticint[] heap = newint[N]; staticint n; publicstaticvoiddown(int i){ int min = i; int l = 2*i; int r = 2*i+1; if(l<=n && heap[l]<heap[min]){ min = l; } if(r <=n && heap[r]<heap[min]){ min = r; } if(min!=i){ int temp = heap[min]; heap[min] = heap[i]; heap[i] = temp; //记得递归down down(min); } } publicstaticvoidmain(String[] args)throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] line = br.readLine().split(" "); n = Integer.parseInt(line[0]); //n个整数 int m = Integer.parseInt(line[1]);//m个数 String[] Strarr = br.readLine().split(" "); for(int i = 1;i<=n;i++){ heap[i] = Integer.parseInt(Strarr[i-1]); } //堆的初始化 for(int i=n/2;i>0;i--){ down(i); } //输出 for(int i=1;i<=m;i++){ System.out.print(heap[1]+" "); heap[1] = heap[n--]; //很关键 down(1); } } }
staticint[] ph=newint[N]; staticint[] hp=newint[N]; staticint idx; //交换值 staticvoidswap(int[] arr, int a, int b){ int tmp=arr[a]; arr[a]=arr[b]; arr[b]=tmp; } //交换ph,和hp,交换值 staticvoidheap_swap(int a, int b){ //ph 指到树上 swap(ph, hp[a], hp[b]); swap(hp, a, b); swap(heap, a, b); } staticvoiddown(int i){ int min=i; int l=i*2; int r=i*2+1; if(l<=size&&heap[l]<heap[t]) min=l; if(r<=size&&heap[r]<heap[t]) min=r;
if(min!=i){ heap_swap(min,i); down(min); } } publicstaticvoidup(int i){ while(i/2>0 && heap[i/2]>heap[i]){ heap_swap(i, i/2); i /= 2; } } publicstaticvoidmain(String[] args)throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); while(n-->0){ String[] line = br.readLine().split(" "); String op = line[0]; if(op.equals("I")){ int x = Integer.parseInt(line[1]); heap[++size]=x; ph[++idx] = size; hp[size]=idx; up(size); }elseif(op.equals("DM")){ heap_swap(1, size); size--; down(1); }elseif(op.equals("D")){ int k = Integer.parseInt(line[1]); int cur = ph[k]; heap_swap(cur, size); size--; down(cur);up(cur); }elseif(op.equals("PM")){ System.out.println(heap[1]); }else{ int k = Integer.parseInt(line[1]); int x = Integer.parseInt(line[2]); int cur = ph[k]; heap[cur]=x; down(cur);up(cur); } } } }