zoukankan      html  css  js  c++  java
  • POJ3368(Frequent values)--线段树

    题目在这里

    3368 Accepted 7312K 1829MS C++ 6936B

    题意为给你一组数据,再给定一组区间,问你这个区间内出现次数最多的元素的次数是多少。

    我还记得这题是学校校赛基础的题目,当时懵懵懂懂的用分治交了6次TLE。知道了线段树之后才后悔每更早的认识她。

    一段区间内的多次出现的数的次数,在线段树查询中有以下几种情况

    1.次数最多的都集中在某一结点的左区间内

    2.次数最多的都集中在某一结点的有区间内

    3.次数最多的在左右两边都有,这时maxCount ==左右两边的maxCount之和

    在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新nSum(加上本次增量),再将增量往下传。这样更新的复杂度就是O(log(n))在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc代表的所有增量累加到nSum上后将Inc清0,接下来再往下查询。

      1 /*************************************************************************
      2     > File Name: poj3368rmq.cpp
      3     > Author: YeGuoSheng
      4     > Description:  
      5     > Created Time: 2019年07月11日 星期四 15时34分56秒
      6  ************************************************************************/
      7 
      8 #include<iostream>
      9 #include<stdio.h>
     10 #include<cstring>
     11 #include<cmath>
     12 #include<vector>
     13 #include<stack>
     14 #include<map>
     15 #include<set>
     16 #include<list>
     17 #include<queue>
     18 #include<string>
     19 #include<algorithm>
     20 #include<iomanip>
     21 using namespace std;
     22 
     23 template <typename T>
     24 struct node
     25 {
     26     int l;
     27     int r;//左右区间端点
     28     T value;
     29     T add;
     30     int lCount;//元素在左边的计数
     31     int rCount;//元素在右边的计数
     32     int maxCount;//总计出现的次数
     33     int Len()const;
     34     int Mid()const;
     35 };
     36 
     37 template <typename T>
     38 int node<T>::Mid()const
     39 {
     40     return (r  + l )/ 2;
     41 }
     42 
     43 template<typename T>
     44 int node<T>::Len()const
     45 {
     46     return (r - l ) +1;
     47 }
     48 
     49 template<typename T>
     50 class IntervalTree
     51 {
     52 protected:
     53     int n;
     54     node<T>*tree;
     55 public:
     56     IntervalTree(int n);
     57     ~IntervalTree();
     58     void BuildTree(int v,int l,int r);
     59     void Add(int v,int l,int r,T m);
     60     T Query(int v,int l,int r);
     61     void Insert(int v,int i,T value);
     62     void BuildCount(int v,int l,int r);
     63     int FindIndexInTree(int v,int y);//在数组下标为u的在树中的下标
     64 };
     65 
     66 template<typename T>
     67 IntervalTree<T>::IntervalTree(int n)
     68 {
     69     this->n = n;
     70     tree = new node<T>[4*n];
     71 }
     72 
     73 template<typename T>
     74 IntervalTree<T>::~IntervalTree()
     75 {
     76     delete []tree;
     77 }
     78 
     79 template<typename T>
     80 void IntervalTree<T>::BuildTree(int v ,int l,int r)
     81 {
     82     tree[v].l =l;
     83     tree[v].r = r;
     84     tree[v].add = 0;
     85     tree[v].value = 0;
     86     if(l == r)//相等
     87     {
     88         tree[v].lCount =tree[v].rCount = tree[v].maxCount = 1;
     89         return ;
     90     }
     91     int mid =(l + r) /2;//二分
     92     BuildTree(v* 2+1,l,mid);
     93     BuildTree(v*2+2,mid+1,r);
     94     tree[v].value = tree[2*v+1].value + tree[2*v+2].value;
     95 }
     96 
     97 
     98 template<typename T>
     99 int IntervalTree<T>::FindIndexInTree(int v,int u)
    100 {
    101     if( tree[v].l == u && tree[v].r == u)
    102     {
    103         return v;
    104     }
    105     else
    106     {
    107         int mid = (tree[v].l + tree[v].r) / 2;
    108         if(u <= mid)
    109         {
    110             FindIndexInTree(v * 2+1,u);
    111         }
    112         else
    113         {
    114             FindIndexInTree(v * 2+2,u);
    115         }
    116     }
    117 }
    118 
    119 template<typename T>
    120 void IntervalTree<T>::BuildCount(int v,int l ,int r)
    121 {
    122     tree[v].l = l;
    123     tree[v].r = r;
    124     if(l == r)
    125     {
    126         tree[v].lCount = tree[v].rCount =tree[v].maxCount = 1; 
    127         return ;
    128     }
    129     int mid  = (l + r )/ 2;
    130     BuildCount(2* v+ 1,l,mid);
    131     BuildCount(2*v +2,mid+1,r);
    132     int repeat = 0;
    133     int leftIndex = FindIndexInTree(v,tree[2*v+1].r);
    134     int rightIndex = FindIndexInTree(v,tree[2*v+2].l);
    135     if(tree[leftIndex].value == tree[rightIndex].value)
    136     {
    137         repeat = tree[2 * v +1].rCount + tree[2*v +2].lCount;
    138     }
    139     else
    140     {
    141         repeat = 0;
    142     }
    143     tree[v].maxCount = max( repeat,max( tree[2*v+1].maxCount, tree[2*v+2].maxCount) );
    144     tree[v].lCount = tree[2*v+1].lCount;
    145     if(tree[2*v + 1].lCount == mid - l + 1 && tree[leftIndex].value==tree[rightIndex].value)
    146     {
    147         tree[v].lCount += tree[2*v +2].lCount;
    148     }
    149     if(tree[2*v + 2].rCount == r- mid  && tree[rightIndex].value==tree[leftIndex].value)
    150     {
    151         tree[v].rCount += tree[2*v +1].rCount;
    152     }
    153 }
    154 template<typename T>
    155 void IntervalTree<T>::Add(int v,int l,int r,T m)//区间的更新操作
    156 {
    157     if(tree[v].l == l && tree[v].r == r)
    158     {
    159         tree[v].add +=m;
    160         return ;
    161     }
    162     tree[v].value += m * (r- l +1);
    163     int mid = (tree[v].l  + tree[v].r) /2;
    164     if( r<= mid)
    165     {
    166         Add(v *2 +1,l,r,m);
    167     }
    168     else
    169     {
    170         if(l > mid)
    171         {
    172             Add(v *2 +2,l,r,m);
    173         }
    174         else
    175         {
    176             Add(v *2 +1,l,mid,m);
    177             Add(v*2+2,mid+1,r,m);
    178         }
    179         
    180     }
    181     
    182 }
    183 template<typename T>
    184 T IntervalTree<T>::Query(int v,int l,int r)//对根结点为v,查询区间l 到 r
    185 {
    186     if(tree[v].l == l && tree[v].r == r)
    187     {
    188         return tree[v].value +(tree[v].r - tree[v].l +1) * tree[v].add;
    189     }
    190     if(tree[v].add != 0)
    191     {
    192         tree[v].value += (tree[v].r - tree[v].l +1) * tree[v].add;
    193         Add( v * 2 +1,tree[v].l,tree[v].Mid(),tree[v].add);
    194         Add( v * 2 +2,tree[v].Mid()+1,tree[v].r,tree[v].add);
    195         tree[v].add = 0;
    196     }
    197     int mid = tree[v].Mid();
    198     if( r <= mid)
    199     {
    200         return     Query(v  * 2 +1,l,r);
    201     }
    202     else
    203     {
    204         if( l > mid)
    205         {
    206             return Query(v * 2+ 2,l ,r);
    207         }
    208         else
    209         {
    210             return Query(v * 2+1,l,mid) + Query(v* 2+2,mid+1,r);
    211         }        
    212     }
    213 }
    214 
    215 template<typename T>
    216 void IntervalTree<T>::Insert(int r,int i,T value)
    217 {
    218     if(tree[r].l == i && tree[r].r == i)
    219     {
    220         tree[r].value= value;
    221         return ;
    222     }
    223     tree[r].value += value;
    224     if(i <= tree[r].Mid())
    225     {
    226         Insert(2*r+1,i,value);
    227     }
    228     else
    229     {
    230         Insert(2 * r+ 2,i,value);
    231     }
    232 }
    233 
    234 int main()
    235 {
    236     int n = 0;
    237     while(cin>>n && n > 0)
    238     {
    239         IntervalTree<int> it(n);
    240         it.BuildTree(0,0,n-1);
    241         int q = 0;
    242         scanf("%d",&q);
    243         for(int i = 0; i< n;i++)
    244         {
    245             int num = 0;
    246             scanf("%d",&num);
    247             it.Insert(0,i,num);
    248         }
    249         it.BuildCount(0,0,n-1);
    250         for(int i =0 ;i < q;i++)
    251         {
    252             int x,y;
    253             cin>>x>>y;
    254             cout<<it.Query(0,x-1,y-1)<<endl;
    255         }
    256     }
    257     return 0;
    258 }
    View Code
  • 相关阅读:
    兼容各浏览器,背景透明,内容不透明
    101 个 MySQL 的调节和优化的提示
    二手房买卖砍价最新攻略 帮你花少钱买好房
    “中国互联网100强”(2013)发布
    写入文件,创建xunlei批量任务
    武汉选房
    Java并发编程(十一)线程池的使用
    Retrofit 代理模式
    Java并发编程(十)阻塞队列
    不要在Android的Application对象中缓存数据!
  • 原文地址:https://www.cnblogs.com/ygsworld/p/11222929.html
Copyright © 2011-2022 走看看