给出一个长度为 n 的非降序序列,求区间 [ l , r ] 内数目最多的元素的数目
线段树
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <cmath>
#include <stdlib.h>
using namespace std;
const double PI = acos(-1.0);
const double eps = 0.1;
const int MAX = 1e5+10;
const int mod = 1e9+7;
int n, q, a[MAX], l, r;
struct node
{
int l, r, lmax, rmax, vmax;
// 区间左右边界, 左最大值, 右最大值,最大值
} lxt[MAX*6];
void build(int pos, int l, int r)
{
lxt[pos].l = l;
lxt[pos].r = r;
if(l==r)
{
lxt[pos].lmax = 1;
lxt[pos].rmax = 1;
lxt[pos].vmax = 1;
return;
}
int mid = (l+r)>>1;
build(pos*2, l, mid);
build(pos*2+1, mid+1, r);
lxt[pos].lmax = lxt[pos*2].lmax;
lxt[pos].rmax = lxt[pos*2+1].rmax;
if(a[lxt[pos*2].r]==a[lxt[pos*2+1].l])//如果左子区间最右边的值等于右子区间最左边的值,考虑合并
{
lxt[pos].vmax = lxt[pos*2].rmax+lxt[pos*2+1].lmax;
if(a[lxt[pos].l]==a[lxt[pos*2+1].l])
lxt[pos].lmax = lxt[pos].vmax;
if(a[lxt[pos].r]==a[lxt[pos*2].r])
lxt[pos].rmax = lxt[pos].vmax;
}
else lxt[pos].vmax = 1;
lxt[pos].vmax = max(lxt[pos].vmax, max(lxt[pos*2].vmax, lxt[pos*2+1].vmax));
}
int solve(int k, int l, int r)
{
if(l<=lxt[k].l&&lxt[k].r<=r)
return lxt[k].vmax;
if(lxt[k*2].r>=r)return solve(k*2, l, r);
if(lxt[k*2+1].l<=l)return solve(k*2+1, l, r);
int ans1, ans2, ans3;
ans1 = solve(k*2, l, lxt[k*2].r);
ans2 = solve(k*2+1, lxt[k*2+1].l, r);
if(a[lxt[k*2].r]==a[lxt[k*2+1].l])ans3 = min(lxt[k*2].r-l+1,lxt[k*2].rmax)+min(r-lxt[k*2+1].l+1, lxt[k*2+1].lmax);
else ans3 = 1;
return max(ans1, max(ans2, ans3));
}
int main()
{
while(~scanf("%d", &n)&&n)
{
scanf("%d", &q);
for(int i = 1; i<=n; ++i)
scanf("%d", &a[i]);
build(1, 1, n);
while(q--)
{
scanf("%d%d", &l, &r);
printf("%d\n", solve(1, l, r));
}
}
return 0;
}