POJ 3368 Frequent values(线段树+离散化)
思路:
首先对给出的序列进行离散化统计,将相同的数字压缩成一个节点,然后统计出这个压缩后的节点在原序列中起点和终点的位置,以及出现的次数等。当然也要记录原数字在离散化后的序列中的位置。
之后就是查询,比方说[a,b]
1.如果a,b属于同一个组,那么区间长度就是我们想要的答案 b-a+1;
2.如果a,b组号相差1,说明该区间被中间截断了,只要分别研究两侧的区间,取大值即可Max(c-a+1,b-c) ---其中c是中间点---
3.如果a,b组号相差大于1,先取出两侧进行研究,取大值,然后再用线段树,算出中间区间的最大值,与刚才的那个数比较,取出最大值即可。
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 100005;
struct Point
{
int left;
int right;
int num;
int count;
}p[MAXN];
int n, q, t, len;
int a[MAXN], hash[MAXN];
struct SegNode
{
int left;
int right;
int num;
int count;
SegNode* lchild;
SegNode* rchild;
void Build(int l, int r);
int Query(int l, int r);
}tree[MAXN*2], *root = tree;
void Init()
{
int i;
for (i = 1; i <= n; i++) scanf("%d", &a[i]);
p[1].left = 1;
p[1].right = 1;
p[1].num = a[1];
p[1].count = 1;
hash[1] = 1;
for (t = 1, i = 2; i <= n; i++)
{
if (a[i] == a[i-1])
{
p[t].count++;
p[t].right = i;
}
else
{
t++;
p[t].left = i;
p[t].right = i;
p[t].num = a[i];
p[t].count = 1;
}
hash[i] = t;
}
}
void SegNode::Build(int l, int r)
{
left = l;
right = r;
if (left == right)
{
num = p[left].num;
count = p[left].count;
lchild = rchild = NULL;
return;
}
int mid = (l+r)>>1;
lchild = &tree[len++];
lchild->Build(l, mid);
rchild = &tree[len++];
rchild->Build(mid+1, r);
if (lchild->count > rchild->count)
{
num = lchild->num;
count = lchild->count;
}
else
{
num = rchild->num;
count = rchild->count;
}
}
int SegNode::Query(int l, int r)
{
if (l == left && r == right) return count;
int mid = (left+right) >> 1;
if (r <= mid) return lchild->Query(l, r);
else if (l > mid) return rchild->Query(l, r);
else
{
int tl = lchild->Query(l, mid);
int tr = rchild->Query(mid+1, r);
return tl > tr ? tl : tr;
}
}
int Solve(int a, int b)
{
if (hash[a] == hash[b]) return b-a+1;
else if (hash[a]+1 == hash[b])
{
int ta = p[hash[a]].right - a + 1;
int tb = b - p[hash[b]].left + 1;
return ta > tb ? ta : tb;
}
else
{
int ta = p[hash[a]].right - a + 1;
int tb = b - p[hash[b]].left + 1;
int qy = root->Query(hash[a]+1, hash[b]-1);
int ans = ta > tb ? ta : tb;
return ans > qy ? ans : qy;
}
}
int main()
{
int a, b;
while (scanf("%d", &n) != EOF, n)
{
scanf("%d", &q);
Init();
len = 1; root->Build(1, t);
while (q--)
{
scanf("%d%d", &a, &b);
printf("%d\n", Solve(a, b));
}
}
}
浙公网安备 33010602011771号