题意: 给你一组数列, 查询区间内有出现次数最多的数的频数
RMQ ,
对于一个区间, 分为两部分, 从 L 开始连续到 T , T + 1 到 R
显然 答案为 MAX (T – L + 1 , RMQ ( T+1, R))
对于 T, 可以先预处理出位置 Pos
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 100000 + 131; int Pos[maxn]; int Num[maxn]; int d[maxn][30]; int Fun[maxn]; int n, m; void RMQ_init() { for(int i = 0; i < n; ++i) d[i][0] = Fun[i]; for(int j = 1; (1<<j) <= n; ++j) for(int i = 0; i + (1<<j) - 1 < n; ++i) d[i][j] = max(d[i][j-1], d[i+(1<<(j-1))][j-1]); } int RMQ(int L, int R) { int k = 0; while((1<<(k+1)) <= R-L+1) k++; return max(d[L][k], d[R-(1<<k)+1][k]); } int main() { while(scanf("%d",&n) != EOF) { if(n == 0) break; scanf("%d",&m); for(int i = 0; i < n; ++i) scanf("%d",&Num[i]); for(int i = 0; i < n; ++i) { if(i == 0) Fun[i] = 1; else { if(Num[i] == Num[i-1]) Fun[i] = Fun[i-1] + 1; else Fun[i] = 1; } } //for(int i = 0; i < n; ++i) cout << Fun[i]; //cout <<endl; //////////////////////// int Now = Num[n-1], pos = n-1; for(int i = n-1; i >= 0; --i) { if(Num[i] == Now) Pos[i] = pos; else { Now = Num[i]; Pos[i] = i; pos = i; } } /*for(int i = 0; i < n; ++i) cout << Pos[i]; cout <<endl;*/ ////////////////////////// RMQ_init(); //cout << RMQ(2,5) <<endl; int l, r; for(int i = 0; i < m; ++i) { scanf("%d%d",&l,&r); l--, r--; int t = Pos[l]; //cout << t << endl; if(t >= r) { printf("%d\n",r-l+1); continue; } else printf("%d\n", max(t-l+1,RMQ(t+1,r))); } } }
时间: 2024-10-24 10:31:36