题目在这里

3368 Accepted 7312K 1829MS C++ 6936B

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

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

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

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

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

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

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

 /*************************************************************************
> File Name: poj3368rmq.cpp
> Author: YeGuoSheng
> Description:
> Created Time: 2019年07月11日 星期四 15时34分56秒
************************************************************************/ #include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<string>
#include<algorithm>
#include<iomanip>
using namespace std; template <typename T>
struct node
{
int l;
int r;//左右区间端点
T value;
T add;
int lCount;//元素在左边的计数
int rCount;//元素在右边的计数
int maxCount;//总计出现的次数
int Len()const;
int Mid()const;
}; template <typename T>
int node<T>::Mid()const
{
return (r + l )/ ;
} template<typename T>
int node<T>::Len()const
{
return (r - l ) +;
} template<typename T>
class IntervalTree
{
protected:
int n;
node<T>*tree;
public:
IntervalTree(int n);
~IntervalTree();
void BuildTree(int v,int l,int r);
void Add(int v,int l,int r,T m);
T Query(int v,int l,int r);
void Insert(int v,int i,T value);
void BuildCount(int v,int l,int r);
int FindIndexInTree(int v,int y);//在数组下标为u的在树中的下标
}; template<typename T>
IntervalTree<T>::IntervalTree(int n)
{
this->n = n;
tree = new node<T>[*n];
} template<typename T>
IntervalTree<T>::~IntervalTree()
{
delete []tree;
} template<typename T>
void IntervalTree<T>::BuildTree(int v ,int l,int r)
{
tree[v].l =l;
tree[v].r = r;
tree[v].add = ;
tree[v].value = ;
if(l == r)//相等
{
tree[v].lCount =tree[v].rCount = tree[v].maxCount = ;
return ;
}
int mid =(l + r) /;//二分
BuildTree(v* +,l,mid);
BuildTree(v*+,mid+,r);
tree[v].value = tree[*v+].value + tree[*v+].value;
} template<typename T>
int IntervalTree<T>::FindIndexInTree(int v,int u)
{
if( tree[v].l == u && tree[v].r == u)
{
return v;
}
else
{
int mid = (tree[v].l + tree[v].r) / ;
if(u <= mid)
{
FindIndexInTree(v * +,u);
}
else
{
FindIndexInTree(v * +,u);
}
}
} template<typename T>
void IntervalTree<T>::BuildCount(int v,int l ,int r)
{
tree[v].l = l;
tree[v].r = r;
if(l == r)
{
tree[v].lCount = tree[v].rCount =tree[v].maxCount = ;
return ;
}
int mid = (l + r )/ ;
BuildCount(* v+ ,l,mid);
BuildCount(*v +,mid+,r);
int repeat = ;
int leftIndex = FindIndexInTree(v,tree[*v+].r);
int rightIndex = FindIndexInTree(v,tree[*v+].l);
if(tree[leftIndex].value == tree[rightIndex].value)
{
repeat = tree[ * v +].rCount + tree[*v +].lCount;
}
else
{
repeat = ;
}
tree[v].maxCount = max( repeat,max( tree[*v+].maxCount, tree[*v+].maxCount) );
tree[v].lCount = tree[*v+].lCount;
if(tree[*v + ].lCount == mid - l + && tree[leftIndex].value==tree[rightIndex].value)
{
tree[v].lCount += tree[*v +].lCount;
}
if(tree[*v + ].rCount == r- mid && tree[rightIndex].value==tree[leftIndex].value)
{
tree[v].rCount += tree[*v +].rCount;
}
}
template<typename T>
void IntervalTree<T>::Add(int v,int l,int r,T m)//区间的更新操作
{
if(tree[v].l == l && tree[v].r == r)
{
tree[v].add +=m;
return ;
}
tree[v].value += m * (r- l +);
int mid = (tree[v].l + tree[v].r) /;
if( r<= mid)
{
Add(v * +,l,r,m);
}
else
{
if(l > mid)
{
Add(v * +,l,r,m);
}
else
{
Add(v * +,l,mid,m);
Add(v*+,mid+,r,m);
} } }
template<typename T>
T IntervalTree<T>::Query(int v,int l,int r)//对根结点为v,查询区间l 到 r
{
if(tree[v].l == l && tree[v].r == r)
{
return tree[v].value +(tree[v].r - tree[v].l +) * tree[v].add;
}
if(tree[v].add != )
{
tree[v].value += (tree[v].r - tree[v].l +) * tree[v].add;
Add( v * +,tree[v].l,tree[v].Mid(),tree[v].add);
Add( v * +,tree[v].Mid()+,tree[v].r,tree[v].add);
tree[v].add = ;
}
int mid = tree[v].Mid();
if( r <= mid)
{
return Query(v * +,l,r);
}
else
{
if( l > mid)
{
return Query(v * + ,l ,r);
}
else
{
return Query(v * +,l,mid) + Query(v* +,mid+,r);
}
}
} template<typename T>
void IntervalTree<T>::Insert(int r,int i,T value)
{
if(tree[r].l == i && tree[r].r == i)
{
tree[r].value= value;
return ;
}
tree[r].value += value;
if(i <= tree[r].Mid())
{
Insert(*r+,i,value);
}
else
{
Insert( * r+ ,i,value);
}
} int main()
{
int n = ;
while(cin>>n && n > )
{
IntervalTree<int> it(n);
it.BuildTree(,,n-);
int q = ;
scanf("%d",&q);
for(int i = ; i< n;i++)
{
int num = ;
scanf("%d",&num);
it.Insert(,i,num);
}
it.BuildCount(,,n-);
for(int i = ;i < q;i++)
{
int x,y;
cin>>x>>y;
cout<<it.Query(,x-,y-)<<endl;
}
}
return ;
}

POJ3368(Frequent values)--线段树的更多相关文章

  1. HDOJ-1806 ( Frequent values ) 线段树区间合并

    http://acm.hdu.edu.cn/showproblem.php?pid=1806 线段树维护区间出现频率最高的出现次数.为了维护上者,需要维护线段前后缀的出现次数,当和其他线段在端点处的字 ...

  2. UVA 11235 Frequent values 线段树/RMQ

    vjudge 上题目链接:UVA 11235 *******************************************************大白书上解释**************** ...

  3. POJ 3368 Frequent values 线段树与RMQ解法

    题意:给出n个数的非递减序列,进行q次查询.每次查询给出两个数a,b,求出第a个数到第b个数之间数字的最大频数. 如序列:-1 -1 1 1 1 1 2 2 3 第2个数到第5个数之间出现次数最多的是 ...

  4. hdu 1806 Frequent values 线段树

    题目链接 给一个非递减数列, n个数, m个询问, 每个询问给出区间[L, R], 求这个区间里面出现次数最多的数的次数. 非递减数列, 这是最关键的一个条件... 需要保存一个区间最左边的数, 最右 ...

  5. poj3368 Frequent values(线段树)

    Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In ad ...

  6. POJ3368 Frequent values(RMQ线段树)

    题目大概说给一个递增序列,询问区间出现最多的数. 用莫队算法比较直观,虽然应该会T..好像也可以主席树..不过题目给的序列是有序的,因而相同的数会聚在一起. 考虑把序列分成一段一段,使每段都包含极大的 ...

  7. [poj3368]Frequent values(rmq)

    题意:给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之间连续出现次数最多的次数. 解题关键:统计次数,转化为RMQ问题,运用st表求解,注意边界. 预处理复杂度:$O(n\log n)$ ...

  8. poj3368 Frequent values

    思路: 转化为RMQ. 实现: #include <cstdio> #include <cstring> #include <algorithm> using na ...

  9. POJ 3368 Frequent values RMQ ST算法/线段树

                                                         Frequent values Time Limit: 2000MS   Memory Lim ...

随机推荐

  1. System.Net.WebRequestMethods.cs

    ylbtech-System.Net.WebRequestMethods.cs 1.返回顶部 1. #region 程序集 System, Version=4.0.0.0, Culture=neutr ...

  2. Android 打开相册拍照选择多张图片显示

    添加依赖: compile 'me.iwf.photopicker:PhotoPicker:0.1.8' compile 'com.jaeger.ninegridimageview:library:1 ...

  3. php nginx window系统 gettext方式实现UTF-8国际化多语言(i18n)

    开始应用: 步骤一:搭建环境(服务器已经完成,环境已经搭建好了) 1.首先查看你的php扩展目录下是否有php_gettext.dll这个文件,如果没有,这就需要你下载一个或是从其他地方拷贝一个,然后 ...

  4. 【438】Python 处理文件

    1. 读取文件,计算 tweets 数目 python中readline判断文件读取结束的方法 line == '' python:如何检查一行是否为空行 line == '\n' or line = ...

  5. CentOS7下搭建Ceph分布式存储架构

    (1).Ceph概述 Ceph是为了优秀的性能.可靠性和可扩展性而设计的统一的.分布式文件系统,并且还是一个开源的分布式文件系统.因为其支持块存储.对象存储,所以很自然的被用做云计算框架opensta ...

  6. Error:java: Compilation failed: internal java compiler

    errorInformation:java: javacTask: 源发行版 1.8 需要目标发行版 1.8 解决此类问题 检查自己的JDK是否一致 1  setting--------built  ...

  7. 邪淫真正的可怕危害 (转自学佛网:http://www.xuefo.net/nr/article54/544414.html)

    邪淫真正的可怕危害 邪淫的害处可能很快就显现,也可能是逐渐的表现出来.但往往后者的害处更大.因为当积累了多年的邪淫果报一旦显现,后悔就已经晚了. 我本人就是一个很好的例子.回想自己这40多年的日子,邪 ...

  8. 【Leetcode_easy】884. Uncommon Words from Two Sentences

    problem 884. Uncommon Words from Two Sentences 题意:只要在两个句子中单词出现总次数大于1次即可. 注意掌握istringstream/map/set的使 ...

  9. git 操作说明

    第一步:代码提交到本地仓库 第二步:更新远程服务器代码到本地,如果有冲突需要优先解决,解决冲突后执行第一步操作 第三步:推送本地代码到远程服务器,可以使用source Tree 或者工具自带的配置gi ...

  10. BP神经网络设计常用的基本方法和实用技术

    尽管神经网络的研究和应用已经取得巨大成功,但在网络的开发设计方面至今仍没有一套完善的理论做指导,应用中采取的主要设计方法是,在充分了解待解决问题的基础上将经验与试探相结合,通过多次改进性试验,最终选出 ...