题意:给出一个大小为n的非降序数字序列,查询区间内出现次数最多的数字出现的次数
思路:如何建树比较难想,建树前需要一些处理
观察一下,数字的范围为-100000-100000,给出的顺序非降序
让每个出现过的数字对应一个区间,a[ ]记录序列,
th[ ] 记录某个位置的数字是出现的第几个数字,cnt[ ]记录这个数字出现的次数,用cnt[ ] 建线段树记录最大值,l[ ] 记录这个数字出现的第一个位置,r[ ]记录出现的最后一个位置
查询时将区间分为三个部分:
一、th[i] + 1 到 th[j] - 1 这几个数字的cnt最大值,查询线段树;
二、th[i] 这个数在查询区间出现的次数,r [ th[ i ] ] - i + 1;
三、 th[j]这个数在查询区间出现的次数,j - l [ th[ j ] ] + 1;
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define lson l, m, rt * 2
#define rson m + 1, r, rt * 2 + 1
int a[100010], th[100010], cnt[100010];
int l[100010], r[100010];
int max[100010 * 4];
void pushup(int rt)
{
max[rt] = max[rt * 2] > max[rt * 2 + 1] ?
max[rt * 2] : max[rt * 2 + 1];
}
void build(int l, int r, int rt)
{
if(l == r)
{
max[rt] = cnt[l];
return;
}
int m = (l + r) / 2;
build(lson); build(rson);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R)
{
return max[rt];
}
int m = (l + r) / 2;
int lmax = 0, rmax = 0;
if(L <= m) lmax = query(L, R, lson);
if(R > m) rmax = query(L, R, rson);
return lmax > rmax ? lmax : rmax;
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int n, q;
while(scanf("%d", &n) != EOF)
{
if(n == 0) break;
scanf("%d", &q);
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
memset(th, 0, sizeof(th));
memset(cnt, 0, sizeof(cnt));
memset(l, 0, sizeof(l));
memset(r, 0, sizeof(r));
memset(max, 0, sizeof(max));
th[0] = 1; cnt[1] = 1; l[1] = 0; r[1] = 0;
int k = 1;
for(int i = 1; i < n; i++)
{ //得到th[],cnt[],l[],r[]
if(a[i] == a[i - 1])
{
th[i] = k;
cnt[k]++; r[k] = i;
}
else
{
k++; th[i] = k;
cnt[k] = 1; l[k] = i; r[k] = i;
}
}
build(1, k, 1);
int x, y, ans;
while(q--)
{
scanf("%d%d", &x, &y);
x--; y--;
if(th[x] == th[y])
{
ans = y - x + 1;
//printf("1:%d %d: %d\n", x, y, ans);
}
else if(th[x] + 1 == th[y])
{
ans = (r[th[x]] - x + 1) > (y - l[th[y]] + 1) ?
(r[th[x]] - x + 1) : (y - l[th[y]] + 1);
//printf("2:%d %d: %d\n", x, y, ans);
}
else
{ //分三部分查询
ans = query(th[x] + 1, th[y] - 1, 1, k, 1);
if(r[th[x]] - x + 1 > ans) ans = r[th[x]] - x + 1;
if(y - l[th[y]] + 1 > ans) ans = y - l[th[y]] + 1;
//printf("3:%d %d: %d\n", x, y, ans);
}
printf("%d\n", ans);
}
}
return 0;
}