POJ_3368_线段树
来源:互联网 发布:java ee web profile 编辑:程序博客网 时间:2024/05/27 00:45
//============================================================================
// Name : POJ_3368.cpp
// Author : tiger
// Description : 给一个非递减序列,询问某一区间内数字出现最高频率
/*
* 思路:在线段树的结点内设5个变量l、r、mx、lf、rf,[l,r]表示该结点的区间范围,
* lf和rf分别表示元素a[l]和a[r]在区间内的出现频率,mx表示区间内的最高出现频率。
* 假设区间[x,y]和[y+1,z]均被询问[i,j]覆盖,则可以分情况讨论区间[x,z]的mx值:
* 若a[y]==a[y+1],则mx[x,y]=max{mx[x,y],mx[y+1,z],rf[x,y]+lf[y+1,z]}
* 否则mx[x,y]=max{mx[x,y],mx[y+1,z]}
* 线段树的应用还是不熟练!!!
*/
//============================================================================
#include <iostream>
using namespace std;
#define MAX 100000
#define min(a,b) (a<b?a:b)
struct NODE
{
int l,r;
int fl,fr;//该区间最左端元素和最右端元素出现频率
int mx;//该区间最高频率
};
int s[MAX+2];
NODE tree[MAX*3];
void build(int v,int l,int r)
{
tree[v].l = l;
tree[v].r = r;
if(l ==r )
{
tree[v].fl = 1;
tree[v].fr = 1;
tree[v].mx = 1;
return;
}
int mid = (l+r)>>1;
build(v*2,l,mid);
build(v*2+1,mid+1,r);
tree[v].fl = tree[v*2].fl;
tree[v].fr = tree[v*2+1].fr;
//左孩子最右边元素和右孩子最左边元素相同
if(s[tree[v*2].r] == s[tree[v*2+1].l])
{
tree[v].mx = (tree[v*2].fr + tree[v*2+1].fl);
//当前节点的最右边元素和右孩子坐左边元素相同,就说明右孩子所有元素相同并且和
//左孩子右边部分元素相同,那么当前节点的右频率 = (tree[v*2].fr + tree[v*2+1].fl);
if(s[tree[v].r] == s[tree[v*2+1].l])
{
tree[v].fr = tree[v].mx;
}
//原理同上
if(s[tree[v].l] == s[tree[v*2].r])
{
tree[v].fl = tree[v].mx;
}
}else
{
tree[v].mx = 1;
}
if(tree[v*2].mx > tree[v].mx )
tree[v].mx = tree[v*2].mx;
if(tree[v*2+1].mx > tree[v].mx )
tree[v].mx = tree[v*2+1].mx;
}
int find(int v,int x,int y)
{
if(x<= tree[v].l && y >= tree[v].r)
return tree[v].mx;
//询问区间在左孩子
if(y <= tree[v*2].r)
{
return find(v*2,x,y);
}
//询问区间在右孩子
if(x >= tree[v*2+1].l)
return find(v*2+1,x,y);
int max = 1,max1,max2;
//左孩子最右边元素和右孩子最左边元素相同
if(s[tree[v*2].r] == s[tree[v*2+1].l])
{
//询问区间有可能未把tree[v*2].fr个元素全包含进去,所以要取min(tree[v*2].r-x+1, tree[v*2].fr)
max =min(tree[v*2].r-x+1, tree[v*2].fr) + min(y - tree[v*2+1].l+1,tree[v*2+1].fl);
}
max1 = find(v*2,x,tree[v*2].r);
max2 = find(v*2+1,tree[v*2+1].l,y);
if(max1 > max)
max = max1;
if(max2 > max)
max = max2;
return max;
}
int main() {
// freopen("in","r",stdin);
int i;
int n,q;
int x,y;
while(scanf("%d %d",&n,&q)&&n)
{
for(i = 1; i <= n; i++)
scanf("%d",s+i);
build(1,1,n);
while(q--)
{
scanf("%d %d",&x,&y);
printf("%d/n",find(1,x,y));
}
}
return 0;
}
- POJ_3368_线段树
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 数据结构的问题求助
- sliverlight :Local connection
- Android体验系列之--Gallery控件
- 邓寿鹏:中国物联网发展存在五个短板
- [水晶报表]实现RDLC 网格显示
- POJ_3368_线段树
- 制作大容量IMG文件或任意调整IMG文件大小的方法
- MBR的反编译程序
- 《物联网产业发展研究(2010)》报告
- 安装Visual Studio 2010之后如何显著提升性能?
- CE开发中可能遇到的问题
- js 限制输入框格式
- "today's topic is 'new age'"
- HTTP实时信息传输方式