HDU 1806 POJ 3368 Frequent values (RMQ)

既然是非降序,,那么相等的点一定都聚集在了一块,然后将相等的点分成一段。然后记录每一段的长度,最右端与最左端,然后记录原数列上每个位置上属于哪一段的标号。然后对于每个询问都可以分成3部分,分别计算每一部分,然后对这三部分取最大值。 代码如下:

;mod=1e9+7;const int INF=0x3f3f3f3f;const double eqs=1e-9;int dp[110000][30], sum[110000], num[110000], lef[110000], righ[110000], cnt, a[110000];void rmq(){int i, j;for(i=1;i<=cnt;i++){dp[i][0]=sum[i];}for(j=1;(1<<j)<=cnt;j++){for(i=1;i<=cnt-(1<<j)+1;i++){dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);}}}int query(int l, int r){if(l>r) return 0;int k=0;while((1<<k+1)<=r-l+1) k++;return max(dp[l][k],dp[r+1-(1<<k)][k]);}int main(){int n, q, i, l, r, j;while(scanf(“%d”,&n)!=EOF&&n){scanf(“%d”,&q);for(i=1;i<=n;i++){scanf(“%d”,&a[i]);}cnt=1;sum[1]=1;num[1]=1;lef[1]=righ[1]=1;for(i=2;i<=n;i++){if(a[i]!=a[i-1]){sum[++cnt]=1;lef[cnt]=righ[cnt]=i;}else{sum[cnt]++;righ[cnt]=i;}num[i]=cnt;}rmq();while(q–){scanf(“%d%d”,&l,&r);if(num[l]==num[r]){printf(“%d\n”,r-l+1);continue ;}int ll=num[l], rr=num[r];int x=sum[ll]-l+lef[ll];int y=sum[rr]-righ[rr]+r;printf(“%d\n”,max(max(x,y),query(num[righ[ll]+1],num[lef[rr]-1])));}}return 0;}

生活若剥去理想、梦想、幻想,那生命便只是一堆空架子

HDU 1806 POJ 3368 Frequent values (RMQ)

相关文章:

你感兴趣的文章:

标签云: