2259: matrix

2259: matrix

时间限制: 1 Sec  内存限制: 256 MB
提交: 185  解决: 34
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

在麦克雷的面前有N个数,以及一个R*C的矩阵。现在他的任务是从N个数中取出 R*C 个,并填入这个矩阵中。矩阵每一行的法值为本行最大值与最小值的差,而整个矩阵的法值为每一行的法值的最大值。现在,麦克雷想知道矩阵的最小法值是多少。

输入

输入共两行。

第一行是三个整数:n,r,c。(r, c <= 104, r * c <= n <= 106

第二行是 n 个整数 Pi。(0 < pi <= 109)

输出

输出一个整数,即满足条件的最小的法值。

样例输入

7 2 3
170 205 225 190 260 225 160

样例输出

30
/*
解法

考虑矩阵中的两行a和b,a1<a2<...<aC
,b1<b2<...<bC,如果aC>b1

,那么交换aC和b1可以得到更优的答案。
所以每一行的值域是不会有交集的。

将所有数升序排序。
设已知答案为ans;
顺序枚举每一个数,如果a[i+C−1]−a[i]<=ans

,我们就可以贪心地把这C个数放进矩阵,枚举完后判断一下是否能够凑齐R行。
证明:
设选取a[i+k]..a[i+k+C-1]会比选取a[i]..a[i+C-1]更优。
设f(x)为[x..n]的最大答案。
那么选取a[i+k]..a[i+k+C-1]能够得到的最大答案即为f(i+k+C)+1;
选取a[i+k]..a[i+C-1]能够得到的最大答案即为f(i+C)+1;
显然f(x)是减函数。
所以与假设违背。

二分答案ans。
就可以将原问题转化为上述问题。


*/


#include<iostream>
#include<algorithm>

using namespace std ;

#define maxn 1100000
int n , r , c ; 
int num[maxn] ; 

bool check(int max_ans){
    int cnt = 0 ;
    for(int i=c ; i<=n ; i++){
        if(num[i] - num[i-c+1] <= max_ans){
            cnt++ ;
            i = i + c-1 ; //后续的 i++ 会修正i值
            if(cnt>=r){
                return true ; 
            }
        }
    }
    return false ; 
}/*
bool check(int limit){
    
    int cnt=0;
    for (int i=1;i<=n-c+1;i++){
        if (num[i+c-1]-num[i]<=limit){
            cnt++;
            i=i+c-1;
            if (cnt>=r) return true;
        }
    }
    return false;
}
*/
int main(){
    int  right =0; 
    cin>>n>>r>>c ; 
    for(int i=1 ; i<=n ; i++)
        cin>>num[i] , right = max(right,num[i]);

    sort(num+1 , num+1+n) ; 

    int left = 0 ;//, right = 1000000001 ; 
    int mid ; 
    while(left<right){
        mid = (left+right)/2 ; 
        if(check(mid)){
            right = mid ; 
        }else{
            left = mid+1 ; 
        }
    }

    cout<<left<<endl ; 
    return 0 ; 
} 


猜你喜欢

转载自www.cnblogs.com/yi-ye-zhi-qiu/p/8905129.html