• 二叉堆(基础)


    知识:

    1.堆分为大根堆和小根堆,是一种相对有序的树形结构。

    大根堆性质:堆中所有元素的值都小于等于堆顶元素,即堆顶是最大元素,所以我们可以用大根堆去维护前m大的值

    小根堆反之。

    形成堆分为几个操作:插入,删除,上浮、下沉

    插入时,我们将将所操作元素插入在堆底最后一位,然后进行上浮。

    上浮:判断该元素是否满足大/小根堆的性质,即比较它和父节点的大小,小根堆:小于父节点时交换,反之。

    删除:将堆顶元素与堆底元素最后一位交换,然后进行下沉。

    下沉:先比对子节点元素大小,将该元素与较小的子节点交换,直到该元素小于等于最小的(小根堆),大根堆反之。

    例题:

    1黑匣子 - 洛谷

    就是使用对顶堆,可以动态维护第i个最值

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. const int N = 2e5 + 10;
    7. int n, m;
    8. int a[N];
    9. priority_queue<int, vector<int>, greater<int>> small;
    10. priority_queue<int> big;
    11. int main()
    12. {
    13. cin >> n >> m;
    14. for (int i = 1; i <= n; i ++ )
    15. cin >> a[i];
    16. // 对顶堆的维护操作 (我们是用小顶堆存小数, 大顶堆存大数), 让对顶堆保持能找到第i小的数
    17. int p = 1;
    18. for (int i = 1; i <= m; i ++ )
    19. {
    20. int x;
    21. cin >> x;
    22. for (int j = p; j <= x; j ++ )
    23. {
    24. big.push(a[j]);
    25. if(big.size() == i)
    26. small.push(big.top()), big.pop();
    27. }
    28. p = x + 1;
    29. cout << small.top() << endl;
    30. big.push(small.top());
    31. small.pop();
    32. }
    33. return 0;
    34. }

    2[NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷

    这道题就是每次找前两个小的合并,然后再插入堆中,贪心的思想

    1. #include
    2. #include
    3. using namespace std;
    4. const int N = 1e5 + 10;
    5. int n, a[N];
    6. priority_queue<int, vector<int>, greater<int>> s;
    7. int main()
    8. {
    9. int n;
    10. cin >> n;
    11. for(int i = 1; i <= n; i ++ )
    12. {
    13. int x;
    14. cin >> x;
    15. s.push(x);
    16. }
    17. int ans = 0;
    18. while(s.size() >= 2)
    19. {
    20. //这道题就是动态将堆中最小的两个值合并
    21. int a = s.top();
    22. s.pop();
    23. int b = s.top();
    24. s.pop();
    25. s.push(a + b);
    26. ans += a + b;
    27. }
    28. cout << ans << endl;
    29. return 0;
    30. }

    3中位数 - 洛谷

    也是使用对顶堆,经典例题,找到每次对半的中间数

    1. #include
    2. #include
    3. using namespace std;
    4. priority_queue<int> big;
    5. priority_queue<int, vector<int>, greater<int>> small;
    6. int n;
    7. int mid;
    8. int main()
    9. {
    10. cin >> n >> mid;
    11. cout << mid << endl;
    12. for(int i = 2; i <= n; i ++ )
    13. {
    14. int x;
    15. cin >> x;
    16. if(x > mid)
    17. small.push(x);
    18. else
    19. big.push(x);
    20. if(i % 2)
    21. {
    22. while(small.size() != big.size())
    23. {
    24. if(small.size() < big.size())
    25. {
    26. small.push(mid);
    27. mid = big.top();
    28. big.pop();
    29. }
    30. else
    31. {
    32. big.push(mid);
    33. mid = small.top();
    34. small.pop();
    35. }
    36. }
    37. cout << mid << endl;
    38. }
    39. }
    40. return 0;
    41. }

    4最小函数值 - 洛谷

    这道题比较水,因为函数式递增的就是开一个大根堆(对内元素<=堆顶元素),然后将第一组系数下的函数值作为对照,小于堆顶元素的就放到堆中,实现动态维护前m个小的数

    1. #include
    2. #include
    3. using namespace std;
    4. const int N = 10010;
    5. int n, m;
    6. int a[N], b[N], c[N];
    7. int ans[N];
    8. priority_queue<int> big; // 求前m小的数
    9. int main()
    10. {
    11. cin >> n >> m;
    12. for(int i = 1; i <= n; i ++ )
    13. {
    14. cin >> a[i] >> b[i] >> c[i];
    15. for(int j = 1; j <= m; j ++ )
    16. {
    17. int k = a[i] * j * j + b[i] * j + c[i];
    18. if(i == 1) // 先把函数1的值当作对照组
    19. {
    20. big.push(k);
    21. }
    22. else
    23. {
    24. if(k < big.top()) // 如果其他函数有小于的,就替换下来
    25. {
    26. big.push(k);
    27. big.pop();
    28. }
    29. else // 这里可以直接break掉,因为这个函数是递增的
    30. break;
    31. }
    32. }
    33. }
    34. for(int i = 1; i <= m; i ++ )
    35. {
    36. ans[i] = big.top();
    37. big.pop();
    38. }
    39. for(int i = m; i >= 1; i -- )
    40. {
    41. cout << ans[i] << ' ';
    42. }
    43. return 0;
    44. }

    5【模板】ST 表 - 洛谷

    st表的作用是求区间最值(RMQ(A,i,j))。

    使用倍增实现的,类似区间dp,f[i][j]存放[i, i + 2^j]之中的最值。

    预处理操作:

    先将f[i][0]填入,然后遍历区间(注意边界值),

    状态转移方程:f[i][j] = max(f[i][j - 1] + f[i - (1 << j - 1)][j - 1]),即[i, i + 2^j - 1 - 1]+[i + 2^j - 1, i + 2^j]

    查询操作:

    类似于预处理操作,len = log2[r - l  + 1],f[l][r] = max(f[l][len], f[r - (1 << len) + 1][len],

    即[l, l + 2^len - 1][r - 2^len + 1, r]

    1. #include
    2. using namespace std;
    3. const int N = 1e5 + 10;
    4. int n, m;
    5. int lg[N];
    6. int f[N][21];
    7. inline int read()
    8. {
    9. int x=0,f=1;char ch=getchar();
    10. while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    11. while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    12. return x*f;
    13. }
    14. int main()
    15. {
    16. cin >> n >> m;
    17. //预处理
    18. lg[0] = -1;
    19. for(int i = 1; i <= n; i ++ )
    20. {
    21. f[i][0] = read();
    22. lg[i] = lg[i >> 1] + 1;
    23. }
    24. for(int j = 1; j <= lg[n]; j ++ )
    25. {
    26. for(int i = 1; i + (1 << j) - 1 <= n; i ++ )
    27. {
    28. f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
    29. }
    30. }
    31. //查询操作
    32. for(int i = 1; i <= m; i ++ )
    33. {
    34. int l, r, ans;
    35. l = read();
    36. r = read();
    37. int len = lg[r - l + 1];
    38. ans = max(f[l][len], f[r - (1 << len) + 1][len]);
    39. printf("%d\n",ans);
    40. }
    41. return 0;
    42. }

    6质量检测 - 洛谷

    st表板子题

    1. #include
    2. using namespace std;
    3. const int N = 1000010;
    4. int n, m;
    5. int f[N][100];
    6. int lg[N];
    7. int main()
    8. {
    9. cin >> n >> m;
    10. //预处理
    11. lg[0] = -1;
    12. for(int i = 1; i <= n; i ++ )
    13. {
    14. cin >> f[i][0];
    15. lg[i] = lg[i >> 1] + 1;
    16. }
    17. for(int j = 1; j <= lg[n]; j ++ )
    18. {
    19. for(int i = 1; i + (1 << j) - 1 <= n; i ++ )
    20. {
    21. f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
    22. }
    23. }
    24. int len = lg[m];
    25. for(int i = 1; i <= n - m + 1; i ++ )
    26. {
    27. int l = i, r = i + m - 1;
    28. int ans = min(f[l][len], f[r - (1 << len) + 1][len]);
    29. cout << ans << endl;
    30. }
    31. return 0;
    32. }

  • 相关阅读:
    ACL访问控制列表的解析和配置
    【技巧】Mac 通过命令查看某个目录下子文件或者子目录的大小
    头歌——机器、深度学习——图像生成
    自学(黑客技术)——网络安全高效学习方法
    【译】C# 11 特性的早期预览
    基础Python教程之pandas使用总结
    Log4j和Log4j2的区别
    记阿里云mysql丢表丢数据的实践记录
    MySQL:一主两从架构
    Allegro阻抗分析指导书
  • 原文地址:https://blog.csdn.net/qq_74593128/article/details/133428131