1. 程式人生 > >UVA - 11235 RMQ

UVA - 11235 RMQ

for oid ++ con tex sin mes pri push

UVA - 11235

題意:給出一個非降序的整數數組,你的任務是對於一系列詢問,回答區間內出現最多的值的次數。

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; }

UVA - 11235 RMQ