POJ 3368/RMQ/线段数
题目链接[http://poj.org/problem?id=3368]
给出一段序列,询问[L,R]区间内最大相同数的个数。
用一个很巧妙地方法,转化成求区间内的最大值的问题。
RMQ维护区间最大值。
MAX处理:
*/
for(int i = 1; i < n; i++) { if(a[i] == a[i - 1]) d[i] = d[i - 1] + 1; else d[i] = 1; }
/*
给出一个序列,1、1、1、1、2、3、4、5.
长度为8,求[2,8];即{1、1、1、2、3、4、5},暴力求出3,(前三个数相同),然后RMQ[5,8],取两者最大值。说一来麻烦,举个栗子。
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int maxn =100000+5; int a[maxn]; int d[maxn]; int dp[maxn][20]; int n,q; int l,r; int RMQ(int l,int r) { int k=log((double)(r-l+1))/log(2.0);//学长的写法,可以的。 return max(dp[l][k],dp[r-(1<<k)+1][k]); } int main () { while(scanf("%d",&n),n) { scanf("%d",&q); for(int i=0;i<n;i++) scanf("%d",&a[i]); d[0]=1; for(int i=1;i<n;i++) { if(a[i]==a[i-1]) d[i]=d[i-1]+1; else d[i]=1; } for(int i=0;i<n;i++) dp[i][0]=d[i]; for(int k=1;(1<<k)<=n;k++) for(int i=0;i+(1<<k)-1<n;i++) dp[i][k]=max(dp[i][k-1],dp[i+(1<<(k-1))][k-1]); for(int i=0;i<q;i++) { scanf("%d%d",&l,&r); l--; r--; if(l>r) continue; if(l==r) printf("1\n"); else { int t=l; while(t<r&&a[t]==a[t+1])t++; int ans=t-l+1; if(t==r||t+1==r) printf("%d\n",ans); else { printf("%d\n",max(ans,RMQ(t+1,r))); } } } } return 0; }
想的太多,做的太少。