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

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

主要处理问题:

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

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

线段树模板:

 

[cpp]  view plain copy
  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. }  

 

优先队列模板:

[cpp]  view plain copy
  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. }  

单调队列模板:

[cpp]  view plain copy
  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. }  

你可能感兴趣的:(优先队列)