UPC10807: 发财兔序列
题目描述
给定一个非降序的由 n 个整数(int)构成的序列以及 q 个由整数(int)i 和 j 构成
的询问。对于每一个询问,输出在 a[i],a[i+1], ... ,a[j-1],a[j]里面出现次
数最多的那个(些)整数出现的次数。
的询问。对于每一个询问,输出在 a[i],a[i+1], ... ,a[j-1],a[j]里面出现次
数最多的那个(些)整数出现的次数。
输入
第一行包含两个整数, n 和 q。
第二行包括 n 个整数 a[1],a[2], ... ,a[n],由空格分开。
以下 q 行每一行包括一个询问,一个询问由两个整数 i 和 j 构成,i 和 j 指示询问索引的边界。保证 i<=j。
第二行包括 n 个整数 a[1],a[2], ... ,a[n],由空格分开。
以下 q 行每一行包括一个询问,一个询问由两个整数 i 和 j 构成,i 和 j 指示询问索引的边界。保证 i<=j。
输出
对于每一组询问,输出一行一个整数:在给定区间内出现次数最多的那个(些)整数出现的次数。
样例输入
复制样例数据
10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
样例输出
1
4
3
提示
#include "bits/stdc++.h" using namespace std; typedef long long ll; const int maxn = 1e5 + 1000; struct node { int l, r, p; } data[maxn]; int cnt[maxn]; int value[maxn]; int dp[maxn][60]; int n, q, p; void init() { for (int i = 0; i < n; i++) { dp[i][0] = cnt[i]; } int k = (int) (log(n * 1.0) / log(2.0)); for (int j = 1; j <= k; j++) { for (int i = 1; i + (1 << j) <= p + 1; i++) { dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } } } int rmq(int i, int j) { int m = (int) (log((double) (j - i + 1)) / log(2.0)); int x = max(dp[i][m], dp[j - (1 << m)+1][m]); return x; } int main() { freopen("input.txt", "r", stdin); scanf("%d %d", &n, &q); int l = 0, r = 0, v = 0, t; p = 1; for (int i = 1; i <= n; i++) { scanf("%d", &t); if (t != v && l != 0) { cnt[p] = r - l + 1; value[p] = t; for (int j = l; j <= r; j++) { data[j].l = l; data[j].r = r; data[j].p = p; } p++; r++; l = r; v = t; } else r++; if (l == 0) { l = 1; v = t; } } cnt[p] = r - l + 1; value[p] = v; for (int i = l; i <= r; i++) { data[i].l = l; data[i].r = r; data[i].p = p; } init(); while (q--) { scanf("%d %d", &l, &r); if (data[l].p == data[r].p) { printf("%d\n",r-l+1); } else { int ll = data[l].p + 1; int rr = data[r].p - 1; int ans = data[l].r - l + 1; ans = max(ans, r - data[r].l + 1); if (ll <= rr) { ans = max(ans, rmq(ll, rr)); } printf("%d\n",ans); } } return 0; }