poj3368
题意:给出一个不降数列,并多次询问某区间内出现次数最多的数字在该区间内的出现频数。
分析:线段树的题,似乎也可以用rmq. 这个题的难点在于查询,因为首先要把相同的数据归为一块(unique),并标记每个块中有多少个数字。
由于这个数列是不降的,所以相同的数字在数列里一定是连续出现的。
建树,并将每个块插入的树中作为一个叶子节点。
这样查询时相当于l,r边界与题中给出的i,j是两个概念。所以此线段树需要两重边界。询问的时候要做特殊的边界处理。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define maxn 101
struct node
{
int s, e;
node *left, *right;
int num, value, num1;
} tree[maxn * 2], f[maxn];
int n, q, ncount;
void buildtree(node *proot, int s, int e)
{
proot->s = s;
proot->e = e;
proot->value = -1;
proot->num = 0;
if (s == e)
return;
ncount++;
proot->left = tree + ncount;
ncount++;
proot->right = tree + ncount;
buildtree(proot->left, s, (s + e) / 2);
buildtree(proot->right, (s + e) / 2 + 1, e);
}
void init()
{
int j = 0, a;
scanf("%d", &f[0].value);
f[0].num = 1;
f[0].num1 = 1;
for (int i = 1; i < n; i++)
{
scanf("%d", &a);
if (a == f[j].value)
f[j].num++,f[j].num1++;
else
{
j++;
f[j].num = 1;
f[j].num1 = f[j - 1].num1 + 1;
f[j].value = a;
}
}
n = j;
}
void insert(node *proot, node &a, int i)
{
if (a.num > proot->num)
{
proot->num = a.num;
proot->value = a.value;
}
if (proot->s == proot->e)
return;
int mid = (proot->s + proot->e) / 2;
if (i <= mid)
insert(proot->left, a, i);
else
insert(proot->right, a, i);
}
void query(node *proot, int i, int j, node &a)
{
int mid = (proot->s + proot->e) / 2;
int as, ae;
if (proot->s == 0)
as = 1;
else
as = f[proot->s - 1].num1 + 1;
ae = f[proot->e].num1;
if (i == as && j == ae)
{
a.num = proot->num;
a.value = proot->value;
return;
}
if (proot->s == proot->e)
{
a.num = j - i + 1;
a.value = proot->value;
return;
}
node b, c;
b.num = 0;
c.num = 0;
if (i <= f[mid].num1)
query(proot->left, i, min(f[mid].num1, j), b);
if (j > f[mid].num1)
query(proot->right, max(f[mid].num1 + 1, i), j, c);
if (b.num > c.num)
{
a.num = b.num;
a.value = b.value;
}
else
{
a.num = c.num;
a.value = c.value;
}
}
int main()
{
//freopen("D:\\t.txt", "r", stdin);
while (scanf("%d", &n) != EOF && n != 0)
{
scanf("%d", &q);
ncount = 0;
init();
buildtree(tree, 0, n);
for (int i = 0; i <= n; i++)
insert(tree, f[i], i);
for (int i = 0; i < q; i++)
{
int a, b;
node temp;
scanf("%d%d", &a, &b);
query(tree, a, b, temp);
printf("%d\n", temp.num);
}
}
return 0;
}

浙公网安备 33010602011771号