UVA - 11235 RMQ
题意:给出一个非降序的整数数组,你的任务是对于一系列询问,回答区间内出现最多的值的次数。
tags: 大白书的题果然有意思,智商不够用了
1】注意给出的是非降序的数组,那么相同的数是连在一起的。所以我们可以先游程编码,即比如 -1 -1 1 1 1 1 3 10 10 10 变为 (1,2) 、(2,4)、(3,1)、(4,3)。
2】然后询问 l, r , 如果 l, r 在同一个块里,就直接减;否则,答案就是 max( 左边块占有的长度,右边块占有的长度,中间所有块的最大值 )。 而中间所有块的最大值用 RMQ 解决。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 100005; int n, q, cnt, a[N], f[N][30]; pair< int, int > p[N]; void Init_RMQ() { rep(i,1,cnt) f[i][0]=p[i].se; for(int j=1; (1<<j)<=cnt; ++j) for(int i=1; i+(1<<j)-1<=cnt; ++i) f[i][j] = max(f[i][j-1], f[i+(1<<(j-1))][j-1]); } int query(int l, int r) { if(r-l+1<=0) return 0; int lg = floor(log2(r-l+1)); return max(f[l][lg], f[r-(1<<lg)+1][lg]); } int id[N], num[N]; int solve(int ql, int qr) { int idl=id[ql], idr=id[qr]; if(idl==idr) return qr-ql+1; return max(num[idl]-ql+1, max(qr-num[idr-1], query(idl+1,idr-1))); } int main() { while(~scanf("%d", &n), n) { scanf("%d", &q); cnt = 0; a[0]=INF; rep(i,1,n) { scanf("%d", &a[i]); if(a[i]!=a[i-1]) p[++cnt]=MP(a[i],1), num[cnt]=num[cnt-1]+1; else ++p[cnt].se, ++num[cnt]; id[i] = cnt; } Init_RMQ(); int ql, qr; while(q--) { scanf("%d%d", &ql, &qr); printf("%d\n", solve(ql, qr)); } } return 0; }