hdu 3486 Interviewe RMQ

hdu 3486 Interviewe RMQ
//hdu 3486 Interviewe

//RMQ



//用RMQ预处理一下,然后进行枚举,具体看代码

//枚举要加优化,要不一样会超时



#define infile freopen("in.txt", "r", stdin);

#include <stdio.h>

#include <string.h>



#define INF (1<<30)

#define N 200005



int dp_max[20][N], log2[N];



inline int max(const int a, const int b)

{

    return a > b? a : b;

}



void rmq(int n)

{

    for(int i = 1; i <= log2[n]+1; ++i)//从第j个开始2^i个数,所以要减1

        for(int j = 1; j + (1<<i) - 1 <= n; ++j)//这里中间那个一定要减1,wa了好多次

            dp_max[i][j] = max(dp_max[i-1][j], dp_max[i-1][j+(1<<(i-1))]);

    //j+(1<<i)-1 减1表示从第j个起的2^i个,包括j所以要减 1

}



int get_max(int from, int to)

{

    int index = log2[to-from+1];

    return max(dp_max[index][from], dp_max[index][to-(1<<index)+1]);

}



int find(int n, int low)    //枚举

{

    int pre_num = -1, pre_tot = -1, pre_sum;

    for(int i = 1; i <= n; ++i) //分成i组

    {

        int num = n / i;    //每组num个

        int sum = num * i;  //总的多少人

        int tot = 0;

        if(num == pre_num)  //如果和前一次一样则从前一次继续累加即可

        {

            tot = pre_tot;

            for(int j = pre_sum + num; j <= sum; j+= num)

            {

                tot += get_max(j - num + 1, j);

                if(tot > low)

                    return i;

            }

            pre_tot = tot;

            pre_sum = sum;

        }

        else

        {

            for(int j = num; j <= sum; j += num)

            {

                tot += get_max(j-num+1, j);

                if(tot > low)

                    return i;

            }

            pre_num = num;

            pre_tot = tot;

            pre_sum = sum;

        }

    }

    return -1;

}



int main()

{

    //infile

    int n, low;

    for(int i = 2; i < N; ++i)

        log2[i] = (i&(i-1)) == 0 ? log2[i-1]+1 : log2[i-1];

    while(scanf("%d%d", &n, &low), n > 0 || low > 0)

    {

        memset(dp_max, 0, sizeof(dp_max));

        for(int i = 1; i <= n; ++i)

            scanf("%d", &dp_max[0][i]);



        rmq(n);



        printf("%d\n", find(n, low));



//一下二分是错的 wa了,下面这组数据答案应该是2,可以卡死

//但别人这组数据过不了也a了,估计我的二分写错了

//10 1500

//1 1 1 1 1000 1000 1 1 1 1



//        int l = 1, h = n;

//        bool flag = false;

//        while(l < h)

//        {

//            int mid = l + (h-l)/2;

//            int num = n / mid, sum = 0;

//            for(int i = 0; i < mid; ++i)

//                sum += get_max(i*num+1, (i+1)*num);

//            if(sum > low)

//            {

//                flag = true;

//                h = mid;

//            }

//            else

//                l = mid + 1;

//        }

//        if(l == h && flag == true)

//            printf("%d\n", l);

//        else

//            puts("-1");

    }

    return 0;

}

 

二杰的二分
#include <stdio.h>

#include <string.h>



const int N = 200005;



int log2[N];

int rmqMax[N][20];//表示从i到i+(2^j)-1最大的值



void init()

{

    log2[1] = log2[0] = 0;

    for(int i = 2; i < N; ++i)

    {

        log2[i] = log2[i-1];

        if(((i-1)&i) == 0)

            log2[i]++;

    }

}



inline int max(const int a, const int b)

{

    return a > b? a : b;

}



inline int query(int a, int b)

{

    int k = log2[(b-a)+1]+1;

    return max(rmqMax[a][k-1], rmqMax[b-(1<<(k-1))+1][k-1]);

}



int getAns(int key, int step)

{

    int ans = 0;

    for(int i = 1; i+step-1 <= step*key; i += step)

    {

        ans += query(i, i+step-1);

    }

    return ans;

}



int binaryFind(int left, int right, int k, int n)

{

    int tt = 0;

    for(int i = 1; i <= n; ++i)

        tt += rmqMax[i][0];

    if(tt <= k)

        return -1;

    int mid;

//对组数二分,不是对每组多少人二分

    while(left != right)

    {

        mid = (left+right)/2;

        int num = n/mid;



        int ans = getAns(mid,num);



        if(ans > k)

            right = mid;

        else

            left = mid+1;

    }



    return right;

}



int main(void)

{

   // comein

    int n, k;

    init();

    while(scanf("%d%d", &n, &k) == 2 && n>0 && k>0)

    {

        for(int i = 1; i <= n; ++i)

        {

            scanf("%d", &rmqMax[i][0]);

        }

        for(int j = 1; j < 20; ++j)

        {

            for(int i = 1; i+(1<<(j-1)) <= n; ++i)

            {

                rmqMax[i][j] = max(rmqMax[i][j-1], rmqMax[i+(1<<(j-1))][j-1]);

            }

        }

//        int a, b;

//        while(scanf("%d%d", &a, &b) == 2)

//        {

//            int ans = query(a, b);

//            printf("%d\n", ans);

//        }

        int ans = binaryFind(1, n, k, n);

        printf("%d\n", ans);

    }

    return 0;

}

 

你可能感兴趣的:(interview)