hdu 3486 RMQ+二分 简单应用
2013-01-30 14:29
288 查看
题目大意: 给定n个数的序列,让我们找前面k个区间的最大值之和,每个区间长度为n/k,如果有剩余的区间长度不足n/k则无视之。现在让我们找最小的k使得和严格大于m。n<=20万,m
<= 10亿。
<= 10亿。
#include<iostream> #include<cmath> #include<cstdlib> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define M 222222 #define MAXN 500 #define MAXM 500 int dp[M][30]; int dp2[MAXN][MAXM][10][10]; int l[M],r[M],a[M]; char s[1002]; /* *一维RMQ ST算法 *构造RMQ数组 makermq(int n,int b[]) O(nlog(n))的算法复杂度 *dp[i]j] 表示从i到i+2^j -1中最大的一个值 *dp[i][j]=max{dp[i][j-1],dp[i+2^(j-1)][j-1]} *查询RMQ rmq(int s,int v) *将s ->v 分成两个2^k的区间 *即 k=(int)log2(s-v+1) *查询结果应该为 max(dp[s][k],dp[v-2^k+1][k]) */ int rmq(int s,int v) { int k=(int)(log((v-s+1)*1.0)/log(2.0)); return max(dp[s][k],dp[v-(1<<k)+1][k]); } void makermq(int n,int b[]) { int i,j; for(i=1;i<=n;i++) dp[i][0]=b[i]; for(j=1;(1<<j)<=n;j++) for(i=1;i+(1<<j)-1<=n;i++) dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } int check(int len,int t,int k) { int i,j,ans=0; for(i=1;i<=t;i++) { ans+=rmq((i-1)*len+1,i*len); if(ans>k)return 1; } return 0; } /* *二维RMQ ST算法 *构造RMQ数组 makermq(int n,int m,int b[][]) O(n*m*log(n)*log(m))算法复杂度 *dp2[row][col][i][j] 表示 行从row ->row +2^i-1 列从col ->col +2^j-1 二维区间里最大值 *dp2[row][col][i][j] = 下行 *max{dp2[row][col][i][j-1],dp2[row][col][i-1][j],dp2[row][col+2^(j-1)][i][j-1],dp2[row+2^(i-1)][col][i-1][j]} *查询RMQ rmq(int sx,int ex,int sy,int ey) *同一维的将sx->ex 分为两个2^kx区间 将 sy->ey分为两个2^ky的区间 *kx=(int)log2(ex-sx+1) ky=(int)log2(ey-sy+1) *查询结果为 *max{dp2[sx][sy][kx][ky],dp2[sx][ey-2^ky+1][kx][ky],dp2[ex-2^kx+1][sy][kx][ky],dp2[ex-2^kx+1][ey-2^ky+1][kx][ky]} */ void makermq(int n,int m,int b[][MAXM]) { int row,col,i,j; for(row=1;row<=n;row++) for(col=1;col<=m;col++) dp2[row][col][0][0]=b[row][col]; for(i=0;(1<<i)<=n;i++) for(j=0;(1<<j)<=m;j++) { if(i==0&&j==0) continue; for(row=1;row+(1<<i)-1<=n;row++) for(col=1;col+(1<<j)-1<=m;col++) { if(i==0) dp2[row][col][i][j]=max(dp2[row][col][i][j-1],dp2[row][col+(1<<(j-1))][i][j-1]); else dp2[row][col][i][j]=max(dp2[row][col][i-1][j],dp2[row+(1<<(i-1))][col][i-1][j]); } } } int rmq(int sx,int ex,int sy,int ey) { int kx=(int)(log((ex-sx+1)*1.0)/log(2.0)),ky=(int)(log((ey-sy+1)*1.0)/log(2.0)); return max(max(dp2[sx][sy][kx][ky],dp2[sx][ey-(1<<ky)+1][kx][ky]),max(dp2[ex-(1<<kx)+1][sy][kx][ky],dp2[ex-(1<<kx)+1][ey-(1<<ky)+1][kx][ky])); } int main() { int u,v,n,q,m; //freopen("//media/学习/ACM/input.txt","r",stdin); while(scanf("%d%d",&n,&q),(n>=0&&q>=0)) { int i,j,l=1,r=n,ans=-1; for(m=0,i=1;i<=n;i++)scanf("%d",&a[i]),m+=a[i]; if(m<=q){printf("%d\n",ans);continue;} makermq(n,a); while(l<=r) { int mid=(l+r)>>1; if(check(n/mid,mid,q)) r=mid-1,ans=mid; else l=mid+1; } printf("%d\n",ans); } return 0; }
相关文章推荐
- HDU 3486 Interviewe【二分+rmq】
- hdu 3486 Interviewe 二分+RMQ
- 【HDU 3486】【二分+RMQ】 Interviewe 【最小化区间个数m,使得每个区间最大值和大于k】
- hdu 3486(RMQ应用)
- hdu 3486 Interviewe(二分+rmq)
- HDU 3486 RMQ+二分
- HDU 3486 Interviewe(RMQ+二分)
- hdu 3486 Interviewe (二分+RMQ)
- hdu 3486 Interviewe (RMQ+二分)
- hdu 3486 Interviewe (二分+RMQ)
- Hdu 3486 Interviewe(二分+RMQ)
- hdu 5875 Function 二分+rmq
- //HDU1848,SG函数,简单应用示例
- HDU-3746Cyclic Nacklace,next数组简单应用。
- HDU 3585 maximum shortest distance 最大团+简单的二分思想
- hdu 2648(map简单应用)
- HDU 3486 RMQ + 二分
- HDU 1541 Stars 树状数组简单应用
- hdu_1222_欧几里得_gcd简单应用_欧几里得扩展性质
- HDU 3603 二分+RMQ