UVA-11235 Frequent values (RMQ)
题目大意:在一个长度为n的不降序列中,有m次询问,每次询问(i,j)表示在区间(i,j)中找出出现次数最多的元素的出现次数。
题目分析:因为序列有序,可以将序列分段,并且记录每段的元素个数、每一个元素所属的段num(i)、每一个元素所属段的左端点l(i)及右端点r(i)。那么对于每次询问:
ans(i,j)=max(max(r(i)-i+1,j-l(j)+1),rmq(num(i)+1,num(j)-1))。
ans(i,j)=r-j+1 (如果i与j属于同一段)
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<vector> # include<queue> # include<list> # include<set> # include<map> # include<string> # include<cmath> # include<cstdlib> # include<algorithm> using namespace std; # define LL long long const int N=1005; const int INF=1000000000; const LL oo=0x7fffffffffffffff; const double eps=1e-10; int n,m; int a[N*100]; vector<int>v; int num[N*100]; int L[N*100]; int R[N*100]; int d[N*100][20]; void RMQ_init() { int len=v.size(); for(int i=0;i<len;++i) d[i][0]=v[i]; for(int j=1;(1<<j)<=len;++j) for(int i=0;i+(1<<j)-1<len;++i) d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]); } void init() { v.clear(); int cnt=1; num[0]=0; L[0]=0; for(int i=1;i<n;++i){ if(a[i]==a[i-1]){ ++cnt; num[i]=num[i-1]; L[i]=L[i-1]; }else{ v.push_back(cnt); num[i]=v.size(); L[i]=i; cnt=1; } } v.push_back(cnt); R[n-1]=n-1; for(int i=n-2;i>=0;--i){ if(a[i]==a[i+1]) R[i]=R[i+1]; else R[i]=i; } RMQ_init(); } int query(int l,int r) { if(l>r) return 0; int k=0; while((1<<(k+1))<=r-l+1) ++k; return max(d[l][k],d[r-(1<<k)+1][k]); } int solve(int l,int r) { if(num[l]==num[r]) return r-l+1; else{ return max(max(R[l]-l+1,r-L[r]+1),query(num[l]+1,num[r]-1)); } } int main() { while(scanf("%d",&n)&&n) { scanf("%d",&m); for(int i=0;i<n;++i) scanf("%d",a+i); init(); int l,r; while(m--) { scanf("%d%d",&l,&r); --l,--r; printf("%d\n",solve(l,r)); } } return 0; }