zoukankan      html  css  js  c++  java
  • 【JZOJ4790】【NOIP2016提高A组模拟9.21】选数问题

    题目描述

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

    输入

    输入共两行。
    第一行是三个整数:n,r,c。
    第二行是 n 个整数 Pi。

    输出

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

    样例输入

    7 2 3
    170 205 225 190 260 225 160

    样例输出

    30

    数据范围

    30%:1<=n,r,c<=100
    50%:1<=n,r,c<=1000
    100%:1<=r,c<=10^4,r*c<=n<=5*10^5,0

    解法

    考虑矩阵中的两行a和b,a1<a2<...<aCb1<b2<...<bC,如果aC>b1,那么交换aC和b1可以得到更优的答案。
    所以每一行的值域是不会有交集的。


    将所有数升序排序。
    设已知答案为ans;
    顺序枚举每一个数,如果a[i+C1]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<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    #define ll long long
    #define ln(x,y) int(log(x)/log(y))
    #define sqr(x) ((x)*(x))
    using namespace std;
    const char* fin="aP1.in";
    const char* fout="aP1y.out";
    const int inf=0x7fffffff;
    const int maxn=500007;
    int n,m1,m2,i,j,k,tmp,ans,cnt,tmd,l,r,mid;
    int a[maxn];
    bool judge(int limit){
        int i,j,k;
        cnt=0;
        for (j=1;j<=n-m2+1;j++){
            if (a[j+m2-1]-a[j]<=limit){
                cnt++;
                j=j+m2-1;
                if (cnt>=m1) return true;
            }
        }
        return false;
    }
    int main(){
        scanf("%d%d%d",&n,&m1,&m2);
        for (i=1;i<=n;i++) scanf("%d",&a[i]),r=max(r,a[i]);
        sort(a+1,a+n+1);
        l=0;
        while (l<r){
            mid=(l+r)/2;
            if (judge(mid)) r=mid;
            else l=mid+1;
        }
        printf("%d",l);
        return 0;
    }

    启发

    最值套最值可以考虑二分。

  • 相关阅读:
    try catch 和\或 finally 的用法
    postgresql与oracle对比
    今天遇到个let: not found
    NTLM相关
    【搜藏】net use命令拓展
    【shell进阶】字符串操作
    【网摘】网上邻居用户密码
    测试导航
    关系代数合并数据 left join
    真正的程序员
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714895.html
Copyright © 2011-2022 走看看