poj3368
题意:给出一个不降数列,并多次询问某区间内出现次数最多的数字在该区间内的出现频数。
分析:线段树的题,似乎也可以用rmq. 这个题的难点在于查询,因为首先要把相同的数据归为一块(unique),并标记每个块中有多少个数字。
由于这个数列是不降的,所以相同的数字在数列里一定是连续出现的。
建树,并将每个块插入的树中作为一个叶子节点。
这样查询时相当于l,r边界与题中给出的i,j是两个概念。所以此线段树需要两重边界。询问的时候要做特殊的边界处理。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; #define maxn 101 struct node { int s, e; node *left, *right; int num, value, num1; } tree[maxn * 2], f[maxn]; int n, q, ncount; void buildtree(node *proot, int s, int e) { proot->s = s; proot->e = e; proot->value = -1; proot->num = 0; if (s == e) return; ncount++; proot->left = tree + ncount; ncount++; proot->right = tree + ncount; buildtree(proot->left, s, (s + e) / 2); buildtree(proot->right, (s + e) / 2 + 1, e); } void init() { int j = 0, a; scanf("%d", &f[0].value); f[0].num = 1; f[0].num1 = 1; for (int i = 1; i < n; i++) { scanf("%d", &a); if (a == f[j].value) f[j].num++,f[j].num1++; else { j++; f[j].num = 1; f[j].num1 = f[j - 1].num1 + 1; f[j].value = a; } } n = j; } void insert(node *proot, node &a, int i) { if (a.num > proot->num) { proot->num = a.num; proot->value = a.value; } if (proot->s == proot->e) return; int mid = (proot->s + proot->e) / 2; if (i <= mid) insert(proot->left, a, i); else insert(proot->right, a, i); } void query(node *proot, int i, int j, node &a) { int mid = (proot->s + proot->e) / 2; int as, ae; if (proot->s == 0) as = 1; else as = f[proot->s - 1].num1 + 1; ae = f[proot->e].num1; if (i == as && j == ae) { a.num = proot->num; a.value = proot->value; return; } if (proot->s == proot->e) { a.num = j - i + 1; a.value = proot->value; return; } node b, c; b.num = 0; c.num = 0; if (i <= f[mid].num1) query(proot->left, i, min(f[mid].num1, j), b); if (j > f[mid].num1) query(proot->right, max(f[mid].num1 + 1, i), j, c); if (b.num > c.num) { a.num = b.num; a.value = b.value; } else { a.num = c.num; a.value = c.value; } } int main() { //freopen("D:\\t.txt", "r", stdin); while (scanf("%d", &n) != EOF && n != 0) { scanf("%d", &q); ncount = 0; init(); buildtree(tree, 0, n); for (int i = 0; i <= n; i++) insert(tree, f[i], i); for (int i = 0; i < q; i++) { int a, b; node temp; scanf("%d%d", &a, &b); query(tree, a, b, temp); printf("%d\n", temp.num); } } return 0; }