这一个题目是求一个区间内重复数字的最大次数。
这题有一个特点,数字是递增滴,相同的数字肯定是连续的。
将相同的数字看做一个部分,hash保存每个数字属于哪个部分。对所有的部分建一颗二叉树,保存此区间内最大的重复数字的个数。
查询的时候分3中情况
1 在同一个部分,直接 尾 - 头 + 1就是结果
2 只差一个部分,分开算,在各个部分里面重复多少次,比较一下
3 中间有很多个部分,那么可以先根据2计算出两头的,在通过二叉树查询最大的重复数字个数
具体见代码,这题也可以用RMQ做,具体见下一篇:
// segment tree
#include <iostream>
using namespace std;
int arr[100010],hash[100010];
struct Part
{
int s, e, cnt;
}part[100010];
struct Node
{
int l, r, num;
}node[1000001];
int Max(int a, int b)
{
return a > b ? a : b;
}
void build(int l, int r, int u)
{
node[u].l = l;
node[u].r = r;
if (l == r)
{
node[u].num = part[l].cnt;
return ;
}
int mid = (l + r) >> 1;
build(l, mid, 2 * u);
build(mid + 1, r, 2 * u + 1);
node[u].num = Max(node[2 * u].num , node[2 * u + 1].num );
}
int query(int l, int r, int u)
{
if (node[u].l == l && node[u].r == r)
{
return node[u].num;
}
int mid = (node[u].l + node[u].r)>> 1;
if (r <= mid)//all in left child tree
{
return query(l, r, 2 * u);
}
else if (l > mid)//all in right child tree
{
return query(l , r, 2 * u + 1);
}
else
{
return Max(query(l, mid, 2 * u), query(mid + 1, r, 2 * u + 1));
}
}
int main()
{
int n, q;
while (scanf("%d", & n) && n)
{
scanf("%d", & q);
for (int i = 1; i <= n; ++ i)
{
scanf("%d", & arr[i]);
}
memset(part, 0, sizeof(part));
int id = 1;
part[1].s = id;
for (int i = 1; i <= n; ++ i)
{
part[id].cnt ++;
hash[i] = id;
if (arr[i] != arr[i + 1] || i == n)
{
part[id].e = i;
++ id;
part[id].s = i + 1;
}
}
build(1, id - 1, 1);
int a, b;
while (q --)
{
scanf("%d %d", & a, & b);
if (hash[a] == hash[b])//the same part
{
printf("%d\n", b - a + 1);
}
else// two situations
{
int n1 = part[hash[a]].e - a + 1;
int n2 = b - part[hash[b]].s + 1;
int n3 = 0;
if (hash[b] - hash[a] > 1)
{
n3 = query(hash[a] + 1, hash[b] - 1, 1);
}
printf("%d\n", Max(Max(n1, n2),n3));
}
}
}
return 0;
}