zoukankan      html  css  js  c++  java
  • AcWing 121 赶牛入圈(二分,前缀和,离散化,尺取)

    题目链接

    解题思路

      很明显找半径直接二分最小值就行了,但是由于题目给的坐标太大,不可能开一个(10000^2)的二维数组求前缀和来写check函数,所以就需要离散化处理。

    代码

    const int maxn = 5e2+10;
    int c,n,fr[maxn],fc[maxn],pre[maxn][maxn],k_fr,k_fc;
    P ori[maxn];
    bool check(int x) {
        for (int s = 1; s<k_fr; ++s) {
            //二分找半径之内离枚举的行数最远(指行数差最大)的点
            int e = upper_bound(fr+1,fr+k_fr,fr[s]+x-1)-fr;
            --e;
            int l = 1, r = 1, sum = 0;
            //列移动
            while(l<k_fc) {
                while(r<k_fc && fc[r]-fc[l]+1<=x) {
                    sum += pre[e][r]-pre[s-1][r];
                    ++r;
                }
                if (sum>=c) return true;
                sum -= pre[e][l]-pre[s-1][l];
                ++l;
            }
        }
        return false;
    }
    int main() {
        scanf("%d%d",&c,&n);
        for (int i = 1; i<=n; ++i) {
            scanf("%d%d",&fr[i],&fc[i]);
            ori[i] = {fr[i],fc[i]};
        }
        //行、列离散化
        sort(fr+1,fr+n+1); 
        sort(fc+1,fc+n+1);
        k_fr = unique(fr+1,fr+n+1)-fr;
        k_fc = unique(fc+1,fc+n+1)-fc;
        for (int i = 1; i<=n; ++i) {
            int fxx = lower_bound(fr+1,fr+k_fr,ori[i].first)-fr;
            int fyy = lower_bound(fc+1,fc+k_fc,ori[i].second)-fc;
            ++pre[fxx][fyy];
        }
        //求离散化后的前缀和
        for (int i = 1; i<k_fr; ++i)
            for (int j = 1; j<k_fc; ++j)
                pre[i][j] += pre[i-1][j];
        int l = 1, r = 10000;
        while(l<r) {
            int mid = (l+r)>>1;
            if (check(mid)) r = mid;
            else l = mid+1;
        }
        printf("%d
    ",l);
        return 0;
    }
    
  • 相关阅读:
    Netty大小端
    手写简单IOC
    Java线程
    mysql查询性能问题,加了order by速度慢了
    字节码增强技术探索
    Linux 添加定时任务
    一千行 MySQL 学习笔记
    深入浅出Shiro系列
    深入浅出SpringMVC系列~
    来聊一聊 Linux 常用命令 (第二篇)~
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/13308799.html
Copyright © 2011-2022 走看看