csu1364 Interview

对拍了一波才找到的错误,此题我用的是二分答案加倍增查询,实际上query那里我觉得仍然有缺陷,因为每一次我的查找还是在循环找到一个k使得x+2^k <= y,而错的地方也正在此地,一开始没有判断x+2^k > y,反而直接将k=y的二进制下的最大的为1的位置,以后一定要注意边界条件。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<string>
#include<set>
#include<algorithm>
#include<vector>
#include<queue>
#include<list>
#include<cmath>
#include<cstring>
#include<map>
#include<stack>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 2005
#define ull unsigned long long
#define ll long long
#define hashmod 99999839
#define mod 9997
int a[maxn];
int dp[maxn][20],p[20];
int n,k;
//dp(i,j) 表示区间[i,i+2^j]中的最大值
//dp(i,j) = max(dp(i,j-1),dp(i+2^(j-1),j-1);
//dp(i,j) = max(dp(i,j-1),q(i+2^(j-1)+1,i+2^j));
//如果查询[x,y]中的最大值则q(x,y) = max(dp(x,k),q(x+2^k+1,y)),x+2^k <= y,k <= log(y-x)
int bitsearch(int x){
    int l = 0,r = 19,mid,ans;
    while(l <= r){
        mid = (l+r)>>1;
        if(p[mid] > x) r = mid - 1;
        else l = mid + 1,ans = mid; 
    }
    return ans;
}
int query(int x,int y){
    if(x > y) return 0;
    if(x == y) return a[x];
    int k = bitsearch(y);
    while(x + p[k] > y) k--;
    return max(dp[x][k],query(x+p[k]+1,y));
}
bool judge(int m){
    int t = n / m,sum = 0;
    for(int i = 1;i <= t * m;i += t){
        sum += query(i,i+t-1);
    }
    if(sum > k) return true;
    return false;
}
void init(){
    p[0] = 1;
    for(int i = 1;i <= 19;++i) p[i] = p[i - 1] << 1;
}
int main(){
   // freopen("a.in","r",stdin);
   // freopen("b.out","w",stdout);
    init();
    while(~scanf("%d%d",&n,&k)){
        if(n < 0 && k < 0) break;
        memset(dp,0,sizeof(dp));
        int Max = 0;
        for(int i = 1;i <= n;++i) scanf("%d",&a[i]),dp[i-1][0] = max(a[i-1],a[i]),Max = max(Max,a[i]);
        dp[n][0] = a[n];
        int li = bitsearch(n) + 1;
        for(int j = 1;j <= li;++j){
            for(int i = 1;i <= n;++i){
                if(i + p[j] > n){
                    if(i + p[j - 1] <= n) dp[i][j] = max(dp[i][j-1],dp[i+p[j-1]][j-1]);
                    else dp[i][j] = dp[i][j-1];
                    continue;
                }
                dp[i][j] = max(dp[i][j-1],dp[i+p[j-1]][j-1]);
            }
        }
        int l = 1,r = n,mid,ans = -1;
        while(l <= r){
            mid = (l + r) >> 1;
            if(judge(mid)){
                ans = mid;
                r = mid - 1;
            }
            else l = mid + 1;
        }
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2018-08-16 17:17  zhuiyicc  阅读(63)  评论(0编辑  收藏  举报