poj 3368 - RMQ
阿新 • • 發佈:2018-10-31
題目連結:https://vjudge.net/problem/POJ-3368
解題思路:
題目給出不降序列,
令f[i] = v[i]==v[i-1]? f[i]+1 : 1;
查詢區間f[i]的最大值可以RMQ,都是要對l進行剪下,使得v[l]的值是第一次出現的位置才行.
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> using namespace std; typedef long long ll; const int mx = 1e5 + 10; int n,m,a[mx],Max[mx][20]; int up[mx]; void RMQ(int N) { for(int j=1;(1<<j)<=N;j++){ int tmp = 1<<(j-1); for(int i=1;i+tmp<=N;i++) Max[i][j] = max(Max[i][j-1],Max[i+tmp][j-1]); } } int find(int x,int k) { if(k<=0) return 0; int len = log(k)/log(2.0); return max(Max[x][len],Max[x+k-(1<<len)][len]); } int main() { a[0] = 1e9; while(scanf("%d",&n)&&n) { a[n+1] = 1e9; scanf("%d",&m); for(int i=1;i<=n;i++){ scanf("%d",a+i); if(a[i]==a[i-1]) Max[i][0] = Max[i-1][0] + 1; else Max[i][0] = 1; } for(int i=n;i>=1;i--){ if(a[i]==a[i+1]) up[i] = up[i+1]; else up[i] = i; } RMQ(n); int l,r; while(m--){ scanf("%d%d",&l,&r); int ans = min(up[l],r)-l+1; ans = max(ans,find(up[l]+1,r-up[l])); printf("%d\n",ans); } } return 0; }