• 线段树、优先队列、单调队列小结


    原文转自:http://blog.csdn.net/lhshaoren/article/details/7897736

    主要处理问题:

    线段树:区间处理,一般需要对整个区间执行相同的操作,时间复杂度O(log(n))
    优先队列:堆实现,找出最小或最大元素,或者第k小或第k大元素,一般区间内元素个数不变,只有个别元素会发生变化。时间复杂度O(log(n))
    单调队列:设队列中元素从小到大,则如果要插入元素比队尾大,则直接入队。如果比队尾小,则队尾元素出队,直到发现队尾不比插入元素小或者队为空,再入队。

    有规律的更新区间内元素,需要判定队头元素是否符合条件。可以处理最小或最大问题,或者第k小或第k大问题。时间复杂度O(n)
     

    线段树模板:

    1. //求区间内最大值  
    2.   
    3. struct Node  
    4. {  
    5.     int l, r;  
    6.     int _max;  
    7.     Node(){}  
    8.     Node(int l, int r, int _max): l(l), r(r), _max(_max){}  
    9. }node[nMax * 4];  
    10. int A[nMax];  
    11.   
    12. int fmax(int a, int b)  
    13. {  
    14.     return a > b ? a : b;  
    15. }  
    16.   
    17. void build(int rt, int l, int r)//创建  
    18. {  
    19.     if(l < r)  
    20.     {  
    21.         int mid = (l + r) / 2;  
    22.         build(rt * 2, l, mid);  
    23.         build(rt * 2 + 1, mid + 1, r);  
    24.         int _max = fmax(node[rt * 2]._max, node[rt * 2 + 1]._max);  
    25.         node[rt] = Node(l, r, _max);  
    26.     }  
    27.     else if(l == r)  
    28.         node[rt] = Node(l, r, A[l]);  
    29. }  
    30.   
    31. void search(int rt, int l, int r, int &_max)//查询  
    32. {  
    33.     if(node[rt].l == l && node[rt].r == r)  
    34.         _max = node[rt]._max;  
    35.     else  
    36.     {  
    37.         int mid = (node[rt].l + node[rt].r) / 2;  
    38.         if(mid >= r)  
    39.             search(rt * 2, l, r, _max);  
    40.         else if(mid + 1 <= l)  
    41.             search(rt * 2 + 1, l, r, _max);  
    42.         else  
    43.         {  
    44.             int max1, max2;  
    45.             search(rt * 2, l, mid, max1);  
    46.             search(rt * 2 + 1, mid + 1, r, max2);  
    47.             _max = fmax(max1, max2);  
    48.         }  
    49.     }  
    50. }  
    51.   
    52. void update(int rt, int a, int b)//更新  
    53. {  
    54.     if(node[rt].l == node[rt].r)  
    55.         node[rt]._max = b;  
    56.     else  
    57.     {  
    58.         int mid = (node[rt].l + node[rt].r) / 2;  
    59.         if(mid >= a)  
    60.             update(rt * 2, a, b);  
    61.         else if(mid + 1 <= a)  
    62.             update(rt * 2 + 1, a, b);  
    63.         node[rt]._max = fmax(node[rt * 2]._max, node[rt * 2 + 1]._max);  
    64.     }  
    65. }  

    优先队列模板:

    1. //小顶堆  
    2.   
    3. int queue[nMax];  
    4. int N;//总结点数  
    5.   
    6. queue[i] = w;//首先对最后一个节点赋值  
    7. void build(int pos)  
    8. {  
    9.     int p = pos;  
    10.     while(p != 1)  
    11.     {  
    12.         if(queue[p / 2] > queue[p])  
    13.         {  
    14.             int temp = queue[p / 2];  
    15.             queue[p / 2] = queue[p];  
    16.             queue[p] = temp;  
    17.         }  
    18.         else  
    19.             break;  
    20.         p = p / 2;  
    21.     }  
    22. }  
    23.   
    24. queue[1] = w;//对顶点进行新的赋值操作  
    25. void update()  
    26. {  
    27.     int p = 1;  
    28.     int son;  
    29.     while(2 * p <= N)  
    30.     {  
    31.         if(2 * p == N || queue[2 * p] < queue[2 * p + 1])  
    32.             son = 2 * p;  
    33.         else  
    34.             son = 2 * p + 1;  
    35.         if(queue[son] < queue[p])  
    36.         {  
    37.             int temp = queue[son];  
    38.             queue[son] = queue[p];  
    39.             queue[p] = temp;  
    40.         }  
    41.         else  
    42.             break;  
    43.         p = son;  
    44.     }  
    45. }  

    单调队列模板:

    1. //每次取出k个连续元素中最小值  
    2. struct Queue  
    3. {  
    4.     int pos;  
    5.     int w;  
    6.     Queue(){}  
    7.     Queue(int pos, int w): pos(pos), w(w){}  
    8. }queue[nMax];  
    9. int N, K;  
    10.   
    11. void update()  
    12. {  
    13.     int front, rear;  
    14.     front = rear = 0;  
    15.     int i;  
    16.     for(i = 1; i <= N; ++ i)  
    17.     {  
    18.         while(front != rear && queue[front - 1].w > A[i]) front --;//入队  
    19.         queue[front ++] = Queue(i, A[i]);  
    20.         if(i >= K)  
    21.         {  
    22.             while(queue[rear].pos <= i - K)//排除  
    23.                 rear ++;  
    24.             printf("%d ", queue[rear]);//取出数据  
    25.         }  
    26.     }  
    27. }  
  • 相关阅读:
    CentOS6.5(1)----设置静态IP并禁用IPV6
    CentOS7运维管理笔记(12)----修改主机名
    重温C语言(1)----计算算术表达式的值
    C++学习笔记(9)----关于变量和数组大小的一道容易出错的面试题
    MySQL数据库(13)----忘记root用户密码解决方案【转载】
    C++学习笔记(8)----C++类的大小
    C++学习笔记(7)----类的数组中构造函数和析构函数的调用顺序
    C++学习笔记(6)----基类和派生类的构造函数和析构函数的执行顺序
    switch的参数类型
    windows下双击可运行的Java软件打包方案(转)
  • 原文地址:https://www.cnblogs.com/10jschen/p/2667406.html
Copyright © 2020-2023  润新知