• 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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    【LA3461】Leonardo的笔记本
    【洛谷P3708】Koishi的数学题
    【Uva11762】Race to 1
    【uva11421】玩纸牌
    【反演复习计划】【51nod1594】Gcd and Phi
    【乱入】Uva11021麻球繁衍
    【反演复习计划】【bzoj4407】于神之怒加强版
    BZOJ3293: [Cqoi2011]分金币
    BZOJ2400: Spoj 839 Optimal Marks
    BZOJ1391: [Ceoi2008]order
  • 原文地址:https://www.cnblogs.com/zhuiyicc/p/9488542.html
Copyright © 2020-2023  润新知