UVA11235 - Frequent values(游程编码+线段树)

题目链接:

https://vjudge.net/problem/UVA-11235


题目大意:

给定一个递增序列,询问一段区间内出现频率最多的数出现的次数。


解题过程:

之前图灵杯比赛的题,当时照着板子敲A的,现在突发奇想补一下题,感觉还是挺简单的,就是用到了游程编码。


题目分析:

由于题目是有序的,那么可以很方便的将一段相同的数合为一个区间,data[i]表示第i段区间元素个数,lb[i]记录第i段区间的左边界,rb[i]记录第i段区间的右边界,用id[i]表示原序列的第i个数处于哪个区间。

那么对于查询l到r的区间,如果lr在同一段区间内,那么显然答案就是r-l+1
如果l和r不在同一段区间,那么答案为以下三个中的最大值,rb[id[l]] - l + 1,r - lb[id[r]] + 1, id[l]+1区间到id[r]-1区间中的最大值`。


AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <bits/stdc++.h>
using namespace std;

const int MAX = 112345;

int tree[MAX<<2];
int data[MAX];

#define lson o<<1
#define rson o<<1|1
#define MID int m = (l+r)/2

void build(int o, int l, int r) {
if (l == r) {
tree[o] = data[l];
return;
}
MID;
build(lson, l, m);
build(rson, m+1, r);
tree[o] = max(tree[lson], tree[rson]);
}

int query(int o, int l, int r, int ql, int qr) {
if (qr < l || r < ql) return 0;
if (ql <= l && r <= qr) {
return tree[o];
}
MID;
return max(query(lson, l, m, ql, qr), query(rson, m+1, r, ql, qr));
}

int raw_data[MAX], n, q, lb[MAX], rb[MAX], id[MAX], top;

void init() {
top = 1;
lb[top] = data[top] = id[1] = 1;
for (int i = 2; i <= n+1; i++) {
if (raw_data[i] != raw_data[i-1] || i == n+1) {
rb[top++] = i-1;
lb[top] = i;
}
data[top]++;
id[i] = top;
}
}

int main() {
//freopen("in", "r", stdin);
//freopen("out", "w", stdout);
while (~scanf("%d", &n) && n) {
scanf("%d", &q);
for (int i = 1; i <= n; i++) {
scanf("%d", raw_data+i);
}
memset(data, 0, sizeof(data));
init();
n = top-1;
build(1, 1, n);
int l, r;
while (q--) {
scanf("%d %d", &l, &r);
//如果l和r在同一个区间内
if (id[l] == id[r]) {
printf("%d\n", r-l+1);
continue;
}
//l和r不在一个区间内
int a = id[l], b = id[r];
a = rb[a] - l + 1;
b = r - lb[b] + 1;
int t = max(a, b);
a = id[l] + 1, b = id[r] - 1;
if (a <= b) {
//查询id[l]+1区间到id[r]-1区间中的最大值
t = max(t, query(1, 1, n, a, b));
}
printf("%d\n", t);
}
}
}