• 刷题记录(NC208250 牛牛的最美味和最不美味的零食)


    NC208250 牛牛的最美味和最不美味的零食

    题目链接

    关键点:

    因为题目是将节点将区间去掉,如何表示区间去掉,可以加一个数num表示当前区间里的元素个数。

    法一:

    区间里的删除节点操作和计算最大最小值的操作,根据当前区间的相对位置来计算

    删除节点(删除第x个节点):

    1. if (tree[2*p].num >= x) dlt(2*p, l, mid, x);//x在左区间
    2. else dlt(2*p+1, mid+1, r, x-tree[p*2].num);

    如果左区间的元素个数大于x,说明x在左区间内

    如果元素个数小于x,说明x在右区间

    查询区间[x, y](第x个元素到第y个元素)

    1. if (tree[p*2].num>=y)//查询区间均在左孩子
    2. return find(2*p, l, mid, x, y);
    3. if (tree[p*2].num//查询区间均在右孩子
    4. return find(2*p+1, mid+1, r, x-tree[2*p].num, y-tree[2*p].num);//[左区间的开端,左区间结束(相对位置)]
    5. ty t1 = find(p*2, l, mid, x, tree[2*p].num);
    6. ty t2 = find(p*2+1, mid+1, r, 1, y-tree[2*p].num);
    7. t1.maxx = max(t1.maxx, t2.maxx);//只要最低和最高
    8. t1.minn = min(t1.minn, t2.minn);
    9. return t1;

    如果左区间的元素个数大于y,说明区间[x, y]全在左区间

    如果左区间元素个数小于x,说明区间[x, y]全在右区间

    否则,[x, y]就包括左右区间,找左区间[x, tree[2*p].num]+右区间[1, y-tree[2*p].num](从1开始)

    完整代码:

    1. # include
    2. using namespace std;
    3. const int N = 1e6+10;
    4. struct ty
    5. {
    6. int maxx, minn, num;
    7. }tree[N*4];
    8. int n, m;
    9. int a[N];
    10. void build(int p, int l, int r)
    11. {
    12. if (l == r)
    13. {
    14. tree[p].maxx = a[l];
    15. tree[p].minn = a[l];
    16. tree[p].num = 1;
    17. return ;
    18. }
    19. int mid = (l+r)/2;
    20. build(2*p, l, mid);
    21. build(2*p+1, mid+1, r);
    22. tree[p].maxx = max(tree[p*2].maxx, tree[2*p+1].maxx);
    23. tree[p].minn = min(tree[p*2].minn, tree[2*p+1].minn);
    24. tree[p].num = tree[2*p].num + tree[2*p+1].num;
    25. }
    26. void dlt(int p, int l, int r, int x)
    27. {
    28. if (l == r)//找到x位置
    29. {
    30. tree[p].maxx = -1e9-10;
    31. tree[p].minn = 1e9+10;
    32. tree[p].num = 0;
    33. return ;
    34. }
    35. int mid = (l+r)/2;
    36. if (tree[2*p].num >= x) dlt(2*p, l, mid, x);//x在左区间
    37. else dlt(2*p+1, mid+1, r, x-tree[p*2].num);
    38. tree[p].maxx = max(tree[p*2].maxx, tree[2*p+1].maxx);
    39. tree[p].minn = min(tree[p*2].minn, tree[2*p+1].minn);
    40. tree[p].num = tree[2*p].num + tree[2*p+1].num;
    41. }
    42. ty find(int p, int l, int r, int x, int y)//(x:当前区间查询区间开端,y:当前区间查询区间开端)
    43. {
    44. if (x==1 && y==tree[p].num)
    45. {
    46. return tree[p];
    47. }
    48. int mid = (l+r)/2;
    49. if (tree[p*2].num>=y)//查询区间均在左孩子
    50. return find(2*p, l, mid, x, y);
    51. if (tree[p*2].num//查询区间均在右孩子
    52. return find(2*p+1, mid+1, r, x-tree[2*p].num, y-tree[2*p].num);//[左区间的开端,左区间结束(相对位置)]
    53. ty t1 = find(p*2, l, mid, x, tree[2*p].num);
    54. ty t2 = find(p*2+1, mid+1, r, 1, y-tree[2*p].num);
    55. t1.maxx = max(t1.maxx, t2.maxx);//只要最低和最高
    56. t1.minn = min(t1.minn, t2.minn);
    57. return t1;
    58. }
    59. int main()
    60. {
    61. scanf("%d%d", &n, &m);
    62. for (int i=1; i<=n; i++)
    63. scanf("%d", &a[i]);
    64. build(1, 1, n);
    65. for (int i=1; i<=m; i++)
    66. {
    67. int k;
    68. scanf("%d", &k);
    69. if (k == 1)
    70. {
    71. int x;
    72. scanf("%d", &x);
    73. dlt(1, 1, n, x);
    74. }
    75. else
    76. {
    77. int x, y;
    78. scanf("%d%d", &x, &y);
    79. ty t;
    80. t = find(1, 1, n, x, y);
    81. printf("%d %d\n", t.minn, t.maxx);
    82. }
    83. }
    84. return 0;
    85. }

    法二:

    先计算好相对位置,然后就可以正常的按照线段树模板来求

    比方说x在线段树的相对位置进行转换

    1. int calc(int p, int l, int r, int x)
    2. {
    3. if (l == r)
    4. return l;
    5. int mid = (l+r)/2;
    6. if (tree[2*p].num>=x) return calc(2*p, l, mid, x);
    7. else return calc(2*p+1, mid+1, r, x-tree[2*p].num);
    8. }

    转换方法与上述同理

    完整代码:

    1. # include
    2. using namespace std;
    3. const int N = 1e6+10;
    4. struct ty
    5. {
    6. int maxx, minn, num;
    7. }tree[N*4];
    8. int n, m;
    9. int a[N];
    10. void build(int p, int l, int r)
    11. {
    12. if (l == r)
    13. {
    14. tree[p].maxx = tree[p].minn = a[l];
    15. tree[p].num = 1;
    16. return ;
    17. }
    18. int mid = (l+r)/2;
    19. build(2*p, l, mid);
    20. build(2*p+1, mid+1, r);
    21. tree[p].maxx = max(tree[p*2].maxx, tree[2*p+1].maxx);
    22. tree[p].minn = min(tree[p*2].minn, tree[2*p+1].minn);
    23. tree[p].num = tree[2*p].num + tree[2*p+1].num;
    24. }
    25. void dlt(int p, int l, int r, int x)
    26. {
    27. if (l == r)//找到x位置
    28. {
    29. tree[p].maxx = -1e9-10;
    30. tree[p].minn = 1e9+10;
    31. tree[p].num = 0;
    32. return ;
    33. }
    34. int mid = (l+r)/2;
    35. if (x<=mid) dlt(2*p, l, mid, x);//x在左区间
    36. else dlt(2*p+1, mid+1, r, x);
    37. tree[p].maxx = max(tree[p*2].maxx, tree[2*p+1].maxx);
    38. tree[p].minn = min(tree[p*2].minn, tree[2*p+1].minn);
    39. tree[p].num = tree[2*p].num + tree[2*p+1].num;
    40. }
    41. ty find(int p, int l, int r, int x, int y)//(x:当前区间查询区间开端,y:当前区间查询区间开端)
    42. {
    43. if (x==l && r == y)
    44. {
    45. return tree[p];
    46. }
    47. int mid = (l+r)/2;
    48. if (y<=mid)//查询区间均在左孩子
    49. return find(2*p, l, mid, x, y);
    50. if (x>mid)//查询区间均在右孩子
    51. return find(2*p+1, mid+1, r, x, y);//[左区间的开端,左区间结束(相对位置)]
    52. ty t1 = find(p*2, l, mid, x, mid);
    53. ty t2 = find(p*2+1, mid+1, r, mid+1, y);
    54. t1.maxx = max(t1.maxx, t2.maxx);//只要最低和最高
    55. t1.minn = min(t1.minn, t2.minn);
    56. return t1;
    57. }
    58. int calc(int p, int l, int r, int x)
    59. {
    60. if (l == r)
    61. return l;
    62. int mid = (l+r)/2;
    63. if (tree[2*p].num>=x) return calc(2*p, l, mid, x);
    64. else return calc(2*p+1, mid+1, r, x-tree[2*p].num);
    65. }
    66. int main()
    67. {
    68. scanf("%d%d", &n, &m);
    69. for (int i=1; i<=n; i++)
    70. scanf("%d", &a[i]);
    71. build(1, 1, n);
    72. for (int i=1; i<=m; i++)
    73. {
    74. int k;
    75. scanf("%d", &k);
    76. if (k == 1)
    77. {
    78. int x;
    79. scanf("%d", &x);
    80. int a = calc(1, 1, n, x);
    81. dlt(1, 1, n, a);
    82. }
    83. else
    84. {
    85. int x, y;
    86. scanf("%d%d", &x, &y);
    87. int a = calc(1, 1, n, x), b = calc(1, 1, n, y);
    88. ty t;
    89. t = find(1, 1, n, a, b);
    90. printf("%d %d\n", t.minn, t.maxx);
    91. }
    92. }
    93. return 0;
    94. }

  • 相关阅读:
    java毕业设计——基于java+Servlet+jsp的网上花店销售系统设计与实现(毕业论文+程序源码)——网上花店销售系统
    kotlin的suspend对比csharp的async&await
    常见的12种二次曲面方程及可视化
    Docker实现Redis Cluster集群 哈希槽分区进行亿级数据存储
    73.C++类模板
    python+vue新生报到宿舍安排管理系统django flask
    【附源码】计算机毕业设计JAVA家政服务网站
    刷题学习记录BUUCTF
    单目结构光三维重建平面不平整
    《Effective C++》条款17
  • 原文地址:https://blog.csdn.net/m0_60531106/article/details/127892647