标签:
http://poj.org/problem?id=3368
给出一个非递减序列,求区间内最多的数字的数量
水题,dp[i][j]记录从 i 开始2^j个数中的出现最多的数,合并dp[i][j]和dp[i+(1<<j)][j]得到dp[i][1<<(j+1)]的时候,由于序列是连续的,只要多考虑一个i+(1<<j)-1(即dp[i][j]所能到达的最右端)上得数字在区间内出现的次数就好了。
#include<stdio.h> #include<math.h> const int N=1e5+2; int dp[N][18]; int mmax(int x,int y) { return x>y?x:y; } int mmin(int x,int y) { return x<y?x:y; } int l[N*2],r[N*2]; void Make_Rmq(int n,int p[]) { for(int i=1;i<=n;++i) { dp[i][0]=p[i]; } for(int j=1;(1<<j)<=n;++j) for(int i=1;i+(1<<j)-1<=n;++i) { int x=dp[i][j-1],y=dp[i+(1<<j-1)][j-1],z=p[i+(1<<j-1)-1]; int mx=mmin(r[x],i+(1<<j)-1)-mmax(l[x],i)+1; dp[i][j]=x; if(mmin(r[y],i+(1<<j)-1)-mmax(l[y],i)+1>mx)dp[i][j]=y,mx=mmin(r[y],i+(1<<j)-1)-mmax(l[y],i)+1; if(mmin(r[z],i+(1<<j)-1)-mmax(l[z],i)+1>mx)dp[i][j]=z,mx=mmin(r[z],i+(1<<j)-1)-mmax(l[z],i)+1; } } int Get_Rmq(int u,int v,int p[]) { int k=(int)(log(v-u+1.0)/log(2.0)); int x=dp[u][k],y=dp[v-(1<<k)+1][k],z=p[u+(1<<k)-1]; int res; int mx=mmin(r[x],v)-mmax(l[x],u)+1; res=x; if(mmin(r[y],v)-mmax(l[y],u)+1>mx)res=y,mx=mmin(r[y],v)-mmax(l[y],u)+1; if(mmin(r[z],v)-mmax(l[z],u)+1>mx)res=z,mx=mmin(r[z],v)-mmax(l[z],u)+1; return res; } int w[N]; void solve() { int n,Q,x,y; w[0]=-1000000000; while(~scanf("%d",&n)&&n) { scanf("%d",&Q); for(int i=1;i<=n;++i) { scanf("%d",&w[i]); w[i]+=100000; if(w[i]!=w[i-1])l[w[i]]=r[w[i]]=i; else ++r[w[i]]; } Make_Rmq(n,w); while(Q--) { scanf("%d%d",&x,&y); int u=Get_Rmq(x,y,w); printf("%d\n",mmin(r[u],y)-mmax(l[u],x)+1); } } } int main() { solve(); return 0; }
标签:
原文地址:http://www.cnblogs.com/kiuhghcsc/p/5731007.html