首页 > 其他分享 >离散化

离散化

时间:2024-08-11 13:37:57浏览次数:4  
标签:le int 离散 坐标 using 奶牛

例题:P3138 [USACO16FEB] Load Balancing S

因为奶牛肯定在奇数坐标上,栅栏必然是偶数坐标位置,因此等价于在每头奶牛 \((x_i,y_i)\) 位置处划两条平行于坐标轴的直线,将平面分成四个区域,计算每个区域奶牛的数量:

  • 左下:\(0 < x \le x_i, \ 0 < y \le y_i\)
  • 左上:\(0 < x \le x_i, \ y > y_i\)
  • 右下:\(x > x_i, \ 0 < y \le y_i\)
  • 右上:\(x > x_i, \ y > y_i\)

而四个区域的奶牛数量可以借助二维前缀和来计算。

但是,题目中的坐标范围是 \(10^6\),我们没法开一个 \(10^6 \times 10^6\) 的二维数组来计算,不管是考虑时间效率还是空间效率都不可行。

注意到 \(n \le 1000\),也就是说最多只有 \(1000\) 头奶牛,也就是说坐标点的取值最多只有 \(2000\) 种不同的数据,而实际上我们只需要能够计算出每个区域的奶牛数量,并不关心坐标具体的数值,只要能保持坐标值的相对大小关系即可。我们可以在保持原数值之间相对大小关系不变的情况下将其映射成正整数,也就是给每个可能用到的数值按照大小关系分配一个编号,用此编号来代替原数值进行操作。这个过程就称为离散化。而离散化之后这个二维前缀和数组大小就只有 \(2000 \times 2000\) 级别了,就可以枚举每头奶牛作为分界点进行计算比较了。

离散化的一种做法是将需要离散化的数值放入一个数组,对其排序,当需要知道某个原始值经过离散化之后映射成多少时利用二分查找返回其在有序数组中的位置即可。

#include <cstdio>
#include <algorithm>
using std::sort;
using std::lower_bound;
using std::max;
using std::min;
const int N = 2005; // 每个坐标有两个数值,离散化之后最多2000个点
int x[N], y[N], d[N], cnt, sum[N][N];
int getid(int num) { // 通过二分查找获取离散化之后的值
    return lower_bound(d + 1, d + cnt + 1, num) - d;
}
int main()
{
    int n;
    scanf("%d", &n); cnt = 2 * n;
    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &x[i], &y[i]);
        d[i] = x[i]; d[i + n] = y[i];
    }
    sort(d + 1, d + cnt + 1); // 将涉及到的数据排序以便离散化
    for (int i = 1; i <= n; i++) {
        int xid = getid(x[i]), yid = getid(y[i]);
        sum[xid][yid]++;
    }
    // 离散化后预处理二维前缀和
    for (int i = 1; i <= cnt; i++)
        for (int j = 1; j <= cnt; j++)
            sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
    int ans = n;
    for (int i = 1; i <= cnt; i++)
        for (int j = 1; j <= cnt; j++) {
            int m = 0;
            int dl = sum[i][j]; m = max(m, dl); // 左下
            int ul = sum[i][cnt] - dl; m = max(m, ul); // 左上 
            int dr = sum[cnt][j] - dl; m = max(m, dr); // 右下
            int ur = n - dl - ul - dr; m = max(m, ur); // 右上
            ans = min(ans, m);
        }
    printf("%d\n", ans);
    return 0;
}

标签:le,int,离散,坐标,using,奶牛
From: https://www.cnblogs.com/ronchen/p/18353276

相关文章

  • 【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和
     ......
  • 【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和
     ......
  • 离散化(特指整数)
    离散化基本含义:离散化,就是把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。注意:离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:原数据:1,888,20000,15;处理后:1,3,4,2;离散化特点:值域大,个数少在离散化中,我们主要会遇到两个问题:1,a数......
  • DAY6 位运算、离散化、区间和并
    本文所有题目都可在acwing题库中找到,本文仅进行归纳整理题目:acwing801给定一个长度为 n的数列,请你求出数列中每个数的二进制表示中 1的个数。输入格式第一行包含整数 n。第二行包含 n个整数,表示整个数列。输出格式共一行,包含 n个整数,其中的第 i个数表示数列中的第......
  • 洛谷题单指南-前缀和差分与离散化-P1904 天际线
    原题链接:https://www.luogu.com.cn/problem/P1904题意解读:给出(左端点,高度,右端点)表示的若干建筑,要输出其轮廓,所谓轮廓就是每个点被覆盖的最高建筑的高度所描绘的线。解题思路:如果能计算每个点被覆盖的最高建筑的高度,用数组h[10005]保存,那么输出轮廓的过程只需要枚举每一个点,如......
  • 离散化-c++
    离散化:一、使用情景值域大e.g.0~1e9个数少e.g.0~1e5二、使用方法将数组中的数映射到从0开始的自然数a[]:1、3、100、2000、50000映射到从0开始的自然数:0,1,2,3,4这个过程就是离散化三、两个问题:1.a数组中最开始可能有重复元素,需要去重vector<int>alls;//存......
  • 基础算法:离散化(C++实现)
    文章目录1.离散化的定义2.离散化例题2.1离散化+二分2.2离散化+哈希表1.离散化的定义离散化是一种在程序设计和算法优化中常用的技术,其核心思想是将无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。具体来说,离散化是在不改变数据相对大小的条......
  • 离散意义下的基础概率与期望
    定义概率:某个随机事件出现的可能性大小。事件\(A\)发生的概率记作\(P(A)\),其取值范围为\([0,1]\)。期望:若\(X\)是一个离散型的随机变量,可能的取值为\(x_1,x_2,\dots,x_n\),对应的概率分别为\(p_1,p_2,\dots,p_n\),那么它的期望值为\(\sum_{i=1}^np_ix_i\)。随机变......
  • 洛谷题单指南-前缀和差分与离散化-P3029 [USACO11NOV] Cow Lineup S
    原题链接:https://www.luogu.com.cn/problem/P3029题意解读:不同的坐标位置有不同种类的牛,要计算一个最小的区间,包括所有种类的牛。解题思路:由于坐标位置不连续,并且数值范围较大,因此需要离散化处理,将坐标处理成1~n连续分布由于种类编号数值范围也比较大,也需要离散化处理,去重后的......
  • 洛谷题单指南-前缀和差分与离散化-P4552 [Poetize6] IncDec Sequence
    原题链接:https://www.luogu.com.cn/problem/P4552题意解读:对一组数字序列,进行若干次区间+1或者-1操作,最终使得所有数字一样,计算最少的操作次数,以及能得到多少种不同序列。解题思路:要使得序列每一个数字都相同,则其差分除了第一项之外其余项都是0。因此,问题转化为:给定一个差分数......