http://acm.hdu.edu.cn/showproblem.php?pid=1806
线段树维护区间出现频率最高的出现次数。为了维护上者,需要维护线段前后缀的出现次数,当和其他线段在端点处的字符相等时,要做合并处理。
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
int n, m;
const int len = ;
int num[len];
struct node
{
int l, r;
int ll, rr;
int v;
};
node tr[len << ];
void pushUp(int rt)
{
tr[rt].v = max(tr[rt << ].v, tr[rt << | ].v);
if (num[tr[rt << ].r] == num[tr[rt << | ].l])
tr[rt].v = max(tr[rt].v, tr[rt << ].rr + tr[rt << | ].ll);
tr[rt].ll = tr[rt << ].ll;
tr[rt].rr = tr[rt << | ].rr;
if (num[tr[rt].l] == num[tr[rt << | ].l])
tr[rt].ll += tr[rt << | ].ll;
if (num[tr[rt].r] == num[tr[rt << ].r])
tr[rt].rr += tr[rt << ].rr;
}
void build(int l, int r, int rt)
{
tr[rt].l = l;
tr[rt].r = r;
if (l == r)
{
tr[rt].v = ;
tr[rt].ll = tr[rt].rr = ;
return;
}
int mid = (l + r) >> ;
build(l, mid, rt << );
build(mid + , r, rt << |);
pushUp(rt);
}
int query(int l, int r, int rt)
{
if (l <= tr[rt].l&&tr[rt].r <= r)
return tr[rt].v;
int mid = (tr[rt].l + tr[rt].r) >> ;
int lr=-, rr=-;
if (l <= mid)
lr = query(l, r, rt << );
if (r > mid)
rr = query(l, r, rt << | );
int ans = max(lr, rr);
if (lr != - && rr != -&&num[mid]==num[mid+])
{
ans = max(ans, min(tr[rt << ].rr,mid-l+) + min(r-mid,tr[rt << | ].ll));
}
//if (ans == 4) cout << tr[rt].l << ' ' << tr[rt].r<<' '<<lr<<' '<<rr<< endl;
return ans;
}
int main()
{
while (scanf("%d", &n) != EOF)
{
if (n == ) break;
scanf("%d", &m);
for (int i = ; i <= n; i++)
scanf("%d", &num[i]);
build(, n, );
while (m--)
{
int l, r;
scanf("%d%d", &l , &r);
printf("%d\n", query(l, r, ));
}
}
return ;
}