HDU 3486 RMQ + 二分
算法:
1.RMQ 求区间最值
2.二分枚举段的数量,注意是段的数量和其和成正比,也就是枚举段的数量。
View Code
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<vector> #include<string> #include<math.h> #include<map> #include<set> #include<algorithm> using namespace std; int v[200010]; int f[200010][21]; int n,k; void pre( ) { memset(f,0,sizeof(f)); for( int i = 1; i <= n; i++) f[i][0] = v[i]; int x = (int) log2(n); for( int j = 1; j <= x; j++) { for( int i = 1; i <= n + 1-(1<<j); i++) { f[i][j] = max(f[i][j-1],f[i + (1<<(j-1))][j-1]); } } } int query( int L, int R ) { int x = (int) log2(R - L + 1); return max(f[L][x],f[R+1-(1<<x)][x]); } bool jugde( int x ) { int sum = 0; int t = n / x; for( int i = 1, k = 1; i <= x; i++, k += t) { sum += query( k, k + t - 1); //printf("a = %d b = %d %d\n",i, i + x - 1, sum); } if( sum > k ) return true; return false; } //分的段数跟和成正比。 int find( int l, int r) { int ans = -1; while( l <= r ) { int mid = (l + r) / 2; if( jugde(mid) ) { ans = mid; r = mid - 1; } else { l = mid + 1; } } return ans; } int main( ) { int a,b; while( scanf("%d%d",&n,&k) != EOF ) { if( n == -1 && k == -1 ) break; for( int i = 1; i <= n; i++) scanf("%d",&v[i]); pre( ); printf("%d\n",find(1,n)); } }
posted on 2012-08-18 17:31 more think, more gains 阅读(141) 评论(0) 编辑 收藏 举报