题目:查询某非递减序列,某些区间中的众数出现的个数。
分析:线段树、离散化。把相同的数字看成一个节点,建立不等分区间树。区间树的节点储存:区间的端点和此区间中的众数的个数。
注意:离散化后并不经过映射建立等分线段树,而是利用原序列中的重复元素的端点建立区间树。
#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;
}