Codility上的问题(39) Silicium 2014

切蛋糕问题:

一个矩形的蛋糕,长为X,宽为Y,沿着X和Y轴各切了刀,形成(N + 1) ^ 2 小块。求面积第K大的块的面积。


函数头部:

int solution(int X, int Y, int K, vector<int> &A, vector<int> &B);


数据范围:

N   [1..40000];

X, Y [2..4 * 10 ^ 8]

相邻两刀之间的距离(包括刀和边界的距离)<=10000

要求复杂度时间: Nlog(N + X + Y)

空间: O(N)

思路: 其实这个题就是杨氏矩阵行列乘积的最大值…… 有复杂度更底的算法…… 对于这个复杂度,用二分就行了。。。当然X,Y要先排序。

二分的思路很简单,从最小块到最大块枚举一个整数,然后看一下它氏第几大的,看它是第几大的时候,可以利用类似于2-sum的方法O(N)实现。

代码:

// you can use includes, for example:
// #include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;


#include <algorithm>


int cal(vector<int> &a,vector<int> &b,long long num) {
int n = a.size(), ans = 0;
    for(int i = 0, j = n - 1; i < n; ++i) {
        for(; (j >= 0) && (a[i] * b[j] > num) ; --j)
        ;
        ans += n - 1 - j;
    }
    return ans;
    
}

int bs(vector<int> &a,vector<int> &b,int k) {
int n = a.size(), left = a[0] * b[0], right = a[n - 1] * b[n - 1];
    while (left <= right) {
        int mid = (left + right) >> 1;
        if (cal(a, b, mid) >= k) {
                left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }
    return right + 1;
}



int solution(int X, int Y, int K, vector<int> &A, vector<int> &B) {
    // write your code in C++11
    A.push_back(X);
    B.push_back(Y);
    for (int i = A.size() - 1; i > 0; --i) {
        A[i] -= A[i - 1];
        B[i] -= B[i - 1];
        
    }
    sort(A.begin(),A.end());
    sort(B.begin(),B.end());
    return bs(A, B, K);
}



你可能感兴趣的:(Codility上的问题(39) Silicium 2014)