UVa 11235 - Frequent values

题目:查询某非递减序列,某些区间中的众数出现的个数。

分析:线段树、离散化。把相同的数字看成一个节点,建立不等分区间树。区间树的节点储存:区间的端点和此区间中的众数的个数。

注意:离散化后并不经过映射建立等分线段树,而是利用原序列中的重复元素的端点建立区间树。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;

int a[ 100001 ];
int l[ 100001 ];
int r[ 100001 ];

//segment_tree__begin
typedef struct tnode
{
	tnode* Lchild;
	tnode* Rchild;
	int    Lvalue;
	int    Rvalue;
	int    Max;
}tnode;
tnode Node[ 200005 ];

class segment_tree 
{
private:
	tnode* Root;
	int    Count;
	tnode* madetree( int a, int b ) {
		tnode* np = &Node[ Count ++ ];
		np->Lvalue = l[a];
		np->Rvalue = r[b];
		np->Lchild = NULL;
		np->Rchild = NULL;
		np->Max = 0;
		if ( a < b ) {
			np->Lchild = madetree( a, (a+b)/2 );
			np->Rchild = madetree( (a+b)/2+1, b );
			np->Max = max( np->Lchild->Max, np->Rchild->Max );
		}else np->Max = r[b]-l[a]+1;
		return np;
	}	
public:
	segment_tree( int a, int b ) {
		Count = 0;
		Root = madetree( a, b );
	}
	int Query( tnode* r, int a, int b ) {
		if ( a == r->Lvalue && b == r->Rvalue ) 
			return r->Max;
		if ( r->Rvalue-r->Lvalue+1 == r->Max )
			return b-a+1;
		if ( r->Lchild->Rvalue >= b ) 
			return Query( r->Lchild, a, b );
		else if ( r->Rchild->Lvalue <= a ) 
			return Query( r->Rchild, a, b );
		else
			return max( Query( r->Lchild, a, r->Lchild->Rvalue ),
						Query( r->Rchild, r->Rchild->Lvalue, b ) );
	}
	int Query( int a, int b ) {
		return Query( Root, a, b );
	}
};
//segment_tree__end
 
int main()
{
	int n,q,x,y; 
	while ( scanf("%d",&n) && n ) {
		scanf("%d",&q);
		for ( int i = 1 ; i <= n ; ++ i )
			scanf("%d",&a[i]);
		 
		int count = 0;	//离散化
		a[0] = -100001;
		for ( int i = 1 ; i <= n ; ++ i )
			if ( a[i] != a[i-1] ) {
				r[count] = i-1;
				count ++;
				l[count] = i;
			}
		r[count] = n;
		
		segment_tree ST( 1, count ); //线段树 
		for ( int i = 1 ; i <= q ; ++ i ) {
			scanf("%d%d",&x,&y);
			printf("%d\n",ST.Query( x, y ));
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值