【马蹄集】—— 搜索专题

news2024/11/25 10:36:25

搜索专题



目录

  • MT2238 数的增殖
  • MT2239 二维矩阵中的最长下降序列
  • MT2240 传染病
  • MT2241 循环空间
  • BD202303 第五维度




MT2238 数的增殖

难度:黄金    时间限制:1秒    占用内存:128M
题目描述

给定一个数 n ( n < 1000 ) n (n<1000) n(n<1000),可以按以下方法进行增殖:

  1. 取原数最高位,在左边加上不大于最高位一半的数;
  2. 不做处理。

现在问最多能生成多少个不同的数。

格式

输入格式:第一行输入一个正整数 n n n
输出格式:一个正整数,表示最多能生成的数的个数。

样例 1

输入:
5

输出:
4

备注

其中: n ≤ 10 3 n\le{10}^3 n103
测试数据中生成了:
5→15
5→25→125
共4个数字(不计算重复数字)。


相关知识点:深度优先搜索


题解


这道题按其意思进行模拟即可。定义两个函数:

函数一:取出当前数的最高位(循环取模实现)。

// 获取数的最高位值
int getHighestOrder(int n)
{
    int highestOrder;
    while(n){
        highestOrder = n%10;
        n /= 10;
    }
    return highestOrder;
}

函数二:对最高位的数 n n n 按要求进行处理,即在当前数 n n n 的前面添加一个数 m   ( m ∈ [ 1 ∼ ⌊ n 2 ⌋ ] ) m\ (m\in\left[1\sim\left\lfloor\frac{n}{2}\right\rfloor\right]) m (m[12n])。显然,函数二是一个递归调用的过程。一旦最高位数 n n n 的一半小于1时,整个过程就停止了(注:这种情况下,这个数本身应该要被算进去,因此要返回 1)。

// 获取数的增值 
int getAddedValue(int n)
{
    int addedValue = 1;
    int halfHighestValue = getHighestOrder(n) / 2;
    for(int i=1; i<=halfHighestValue; i++)
        addedValue += getAddedValue(i);
    return addedValue;
}

基于此,可得到求解本题的完整代码:

/*
    MT2238 数的增值 
    搜索 
*/ 
#include<bits/stdc++.h> 
using namespace std;

// 获取数的最高位值
int getHighestOrder(int n)
{
    int highestOrder;
    while(n){
        highestOrder = n%10;
        n /= 10;
    }
    return highestOrder;
}
// 获取数的增值 
int getAddedValue(int n)
{
    int addedValue = 1;
    int halfHighestValue = getHighestOrder(n) / 2;
    for(int i=1; i<=halfHighestValue; i++)
        addedValue += getAddedValue(i);
    return addedValue;
}

int main( )
{
    // 录入数据 
    int n;cin>>n;
    // 输出数的增值
    cout<<getAddedValue(n)<<endl;
    return 0;
}


MT2239 二维矩阵中的最长下降序列

难度:钻石    时间限制:1秒    占用内存:128M
题目描述

给定一个 n × m n\times m n×m 的矩阵,然后可以随机选取一个点作为起始点,每次可以选择该点的上下左右四个相邻点中的一个并且保证相邻点的值小于当前点的值。问最长下降序列的长度是多少?

格式

输入格式:第一行输入两个正整数 n ,   m   ( 1 ≤ n ,   m ≤ 100 ) n,\ m\ \left(1\le n,\ m\le100\right) n, m (1n, m100)
     接下来 n n n 行,每行 m m m 个数字 a [ i ] [ j ]   ( ( 1 ≤ a [ i ] [ j ] ≤ 4 × 10 4 ) ) a\left[i\right]\left[j\right]\ (\left(1\le a\left[i\right]\left[j\right]\le4{\times10}^4\right)) a[i][j] ((1a[i][j]4×104))
输出格式:输出最长下降序列的长度。

样例 1

输入:
5 4
1 2 3 4
16 17 18 19
15 24 25 20
14 23 22 21
13 12 11 10

输出:
16

备注

样例中,选取起始点 25,然后 25→24→23→……→11→10,长度为 16。


相关知识点:深度优先搜索记忆化搜索


题解


题目的意思是在一个 n × m n\times m n×m 的矩阵中找一个位置,使得从该位置出发(只能往上、下、左、右四个方向行走,且下一个位置上的值必须小于当前位置上的值)能得到最长的路径长度。这是一道非常典型的DFS走迷宫问题。最简单粗暴的方式就是遍历整个矩阵中的全部位置,算出从该位置出发得到的最长路径长度。但遗憾的是,在题目给出的最广可达 100 × 100 100\times100 100×100 的数据范围下,这种办法肯定不能拿到满分。

注意到一个事,该办法超时的原因在于,每次基于某个位置进行深度优先搜索时,都有可能会出现重复计算。例如,下图中,当从值为 14 的位置出发时,它会找到一条长度为 9 的路径(如左图所示)。而当从值为13的位置出发时,它会找那条长度为 8 的路径(如右图所示)。

在这里插入图片描述

若假设顺序为 14、13、……。则在从 14 出发进行深度优先搜索时,它肯定会先计算从 13 出发得到的最长下降子序列;而从 13 出发时,它又会先计算从12出发得到的最长下降子序列……直到该过程结束,并在最后通过回溯得到从 14 出发得到的最长下降子序列长度。此时,当我们再计算 13 的最长子序列时,它也会重复上述过程,这便是大量重复计算的地方。试想,如果我们在求某个点的最长下降子序列时,对其搜索到的所有点的最长子序列长度进行存储,即:

在这里插入图片描述

这样一来,以 14 所在位置为起点涉及到的最长下降序列中的任何点都将在递归过程中找到其自身的最长下降子序列,并且形成记录。这就避免了后续重复寻找 13、12、……、2、1 等值所在位置的最长下降子序列。另一方面,假设现在要求值为 15 的位置处的最长下降子序列,则其只需要做一件事:判断当前这个点是否有更长的下降子序列?如果不是,则当前位置存储的值即为其最大值;否则,就对当前位置继续进行深搜。即,对值为 15 的位置 ( 1 ,   1 ) \left(1,\ 1\right) (1, 1) 而言,它只需做一件事:

p a t h ( 1 , 1 ) = max { p a t h ( 1 , 1 ) , D F S ( n e x t P o i n t ) + 1 } path(1,1)=\text{max}\{path(1,1) ,DFS(nextPoint)+1\} path(1,1)=max{path(1,1),DFS(nextPoint)+1}

其中 nextPoint 表示从点 ( 1 ,   1 ) \left(1,\ 1\right) (1, 1) 出发能走的下一个点(在给出的例子中, ( 1 ,   1 ) \left(1,\ 1\right) (1, 1) 的下一个可行点只有 ( 1 ,   2 ) \left(1,\ 2\right) (1, 2),而根据矩阵中存储的值可知,从点 ( 1 ,   2 ) \left(1,\ 2\right) (1, 2) 出发能得到的最长下降子序列长度为 9 ),于是有:

p a t h ( 1 , 1 ) = max { p a t h ( 1 , 1 ) , 10 } path(1,1)=\text{max}\{path(1,1) ,10\} path(1,1)=max{path(1,1),10}

显然,对位置 ( 1 ,   1 ) \left(1,\ 1\right) (1, 1) 而言,其默认最长下降子序列长度为 p a t h ( 1 , 1 ) = 1 path(1,1)=1 path(1,1)=1(即,仅含自身一个点)。因此,基于以上式子可以直接得到从 ( 1 ,   1 ) \left(1,\ 1\right) (1, 1) 出发的最长下降子序列长度为 10。

我们将以上这种记录前面搜索过程相关结果的搜索称为 “记忆化搜索”。在这种需要计算一个矩阵的最长(或最短)路径问题时,记忆化搜索可以大大降低计算成本。

下面直接给出基于以上思路得到的求解本题的完整代码:

/*
    MT2239 二维矩阵中的最长下降序列 
    深度优先搜索、记忆化搜索 
*/ 

#include<bits/stdc++.h> 
using namespace std;

const int N = 105;
// 存放矩阵的二维表,对应的访问标记表(记录该位置的最长下降序列长度) 
int matrix[N][N], vis[N][N];
// 矩阵规格
int n, m; 
// 四种行走方式(上、下、左、右) 
int forwardX[] = {0, 0, -1, 1};
int forwardY[] = {-1, 1, 0, 0};

// 录入矩阵信息 
void getMatrix()
{
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            cin>>matrix[i][j];
}

// 获取指定位置的最长下降序列长度(带记忆化搜索) 
int DFS(int x, int y)
{
    // 如果已经被访问过,则直接返回该点记录的最长下降序列长度 
    if(vis[x][y]) return vis[x][y];
    // 否则初始化该点的最长下降序列长度为 1 (即自身) 
    vis[x][y] = 1;
    // 向各方向发散寻找最长下降序列
    for(int i=0; i<4; i++){
        int nextx = x + forwardX[i];
        int nexty = y + forwardY[i];
        // 越界或所处位置的数值更大则直接跳过 
        if(nextx < 1 || nextx > n || nexty < 1 || nexty > m || matrix[nextx][nexty] >= matrix[x][y])
            continue;
        // 否则将当前的最大下降子序列进行更新
        vis[x][y] = max(vis[x][y], DFS(nextx, nexty) + 1); 
    } 
    return vis[x][y];
}

// 获取最长下降序列  
int getLongestDesSeq()
{
    int tmp, longestDesSeq = 0;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++){
            tmp = DFS(i, j);
            if(tmp > longestDesSeq)
                longestDesSeq = tmp;
        }
    return longestDesSeq;
}

int main( )
{
    // 录入数据 
    cin>>n>>m;
    getMatrix();
    // 寻找最长下降序列 
    cout<<getLongestDesSeq()<<endl;
    return 0;
}


MT2240 传染病

难度:钻石    时间限制:1秒    占用内存:128M
题目描述

小码哥正在研究传染病的相关知识,现在遇到了这么一个问题:有一个长为 n n n ,宽为 m m m ,高为 k k k (层数)的的长方体,它可以看成 n × m × k n\times m\times k n×m×k 1 × 1 × 1 1\times1\times1 1×1×1 大小的单位正方体。每个单位正方体都有一个字符。.表示该位置防疫措施不好,如果被传染了就会感染病毒。# 表示该区人民防疫措施良好,永远不会感染病毒(甚至都不会成为病毒的携带者)。

现在在长方体的最顶层(层号为 1)某个位置,因实验室泄露爆发了病毒。每过一个单位时间,病毒将扩散至周围 6 个方向的地区。如果某个地区为 #,那么一定不会被感染并且不会携带病毒同时也不会传播病毒。(但如果这个地方存在泄露的实验室,那么哪怕防疫措施再好也会被感染以及传播病毒)。

现在小码哥需要知道,假如第一层坐标为 ( x ,   y ) \left(x,\ y\right) (x, y) 的实验室泄露了病毒,那么最多会有多少区域被感染。

格式

输入格式:第一行三个正整数 k ,   n ,   m   ( k ,   n ,   m ≤ 10 ) k,\ n,\ m\ (k,\ n,\ m\le10) k, n, m (k, n, m10)
     接下来 k k k 层,每层 n n n 行,每行 m m m 个字符,表示长方体每个单位的状态;
      最后一行两个正整数 x ,   y   ( x ≤ n ,   y ≤ m ) x,\ y\ \left(x\le n,\ y\le m\right) x, y (xn, ym) 表示发生泄漏的实验室的坐标(这个实验室在第一层)。

输出格式:按题目要求输出一行一个整数表示答案。

样例 1

输入:

3 3 3

.#.
###
##.

.##
###
##.

...
...
...

1 1

输出:

13


相关知识点:广度优先搜索


题解


这道题实际上就是基于广度优先搜索的走格子问题,不同的是这道题里的空间是一个三维空间。为此,我们只需要在BFS中再额外地添加两种行走方式,然后从题目给出的起点进行行走,并逐个统计感染的实验室个数即可。另外,由于广度优先搜索需要用到队列这一数据结构,故为了方便使用我们单独定义了一个类似“三元组”形式的数据结构(结构体),用于表示三维空间中的一个点。

下面直接给出求解本题的完整代码:

/*
    MT2240 传染病 
    广度优先搜索 
*/ 

#include<bits/stdc++.h> 
using namespace std;

const int N = 13;
// 存放矩阵的二维表,对应的访问标记表
char cube[N][N][N];
int vis[N][N][N];
// 立方体规格
int k, n, m; 
// 六种行走方式(上、下、左、右、前、后) 
int forwardX[] = {0, 0, -1, 1, 0, 0};
int forwardY[] = {0, 0, 0, 0, -1, 1};
int forwardZ[] = {-1, 1, 0, 0, 0, 0};
// 封装三维空间中一个点的数据结构
struct Site{
    int x, y, z;
    Site(){}
    Site(int x, int y ,int z):x(x),y(y),z(z){}
}; 
Site curSite, nextSite;

// 录入立方体信息 
void getCube()
{
    for(int l=1; l<=k; l++)
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                cin>>cube[i][j][l];
}

// 检测下个区域是否可达 
bool check(Site site){
    int x = site.x, y = site.y, z = site.z;
    // 测下个区域是否合法
    if(x<1 || x>n || y<1 || y>m || z<1 || z>k) 
        return false;
    // 测下个区域能否继续传播病毒
    if(vis[x][y][z] || cube[x][y][z] == '#')
        return false;
    return true;
} 

// 计被感染的区块个数(广度优先搜索) 
int getInfectedBlocks(int x, int y)
{
    int infectedBlocks = 0;
    // 初始化队列 
    queue<Site> q;
    q.push(Site(x,y,1));
    vis[x][y][1] = true;
    // 广度优先搜索
    while(!q.empty()){
        // 取出当前队头元素 
        curSite = q.front();
        // 队头元素出队列
        q.pop();
        // 统计被感染数 
        infectedBlocks++;
        // 病毒扩散! 
        for(int i=0; i<6; i++){
            // 扩散后的新位置 
            nextSite.x = curSite.x + forwardX[i];
            nextSite.y = curSite.y + forwardY[i];
            nextSite.z = curSite.z + forwardZ[i];
            // 若新扩散成立
            if(check(nextSite)) {
                // 则入队列 
                q.push(nextSite);
                // 置访问标记为真
                vis[nextSite.x][nextSite.y][nextSite.z] = true;
            }
        }
    }
    return infectedBlocks;
}

int main( )
{
    // 录入数据 
    int x, y; 
    cin>>k>>n>>m;
    getCube();
    cin>>x>>y;
    // 统计被感染的区块个数 
    cout<<getInfectedBlocks(x, y)<<endl;
    return 0;
}


MT2241 循环空间

难度:钻石    时间限制:1秒    占用内存:256M
题目描述

给出一个二维的由0、1、2组成的 n × n n\times n n×n 空间,0 表示障碍物,1 表示可行走,2 表示起点,这个空间是循环的,如走到左边界再往左走,你会出现在右边界对应位置,我们每次能向上、下、左、右中的一个方向行走一格。

请输出从起点到每个点的最短路径长度。

格式

输入格式:第一行一个正整数 n n n ,表示地图的边长;
     接下来 n n n 行,每行 n n n 个整数,0 表示障碍物,1 表示可行走,2 表示起点。
输出格式:输出 n n n 行,每行 n n n 个整数。0 表示起点或无法到达的点,其他数字表示从起点到此处的最短路径长度。

样例 1

输入:
5
0 1 2 1 0
0 0 1 0 1
1 1 0 0 1
1 0 0 1 0
1 1 1 0 0

输出:

0 1 0 1 0
0 0 1 0 7
5 6 0 0 6
4 0 0 0 0
3 2 1 0 0

备注

对于30%的数据: 1 ≤ n ≤ 30 1\le n\le30 1n30
对于60%的数据: 1 ≤ n ≤ 300 1\le n\le300 1n300
对于100%的数据: 1 ≤ n ≤ 2000 1\le n\le2000 1n2000


相关知识点:广度优先搜索


题解


求二维矩阵中指定点到其余所有点的最短距离,一道典型的广度优先搜索题。不过需要注意的是,本题给出的二维矩阵是 “循环” 的,即处于边界位置并继续往边界方向行走时,会直接走到另一个相对的边界。这相当于是对“行走方式”添加了一种新的准则。我们的处理办法也很简单,将新位置在各维度上的值加上整个二维矩阵的规格(避免了向索引降低的方向行走时出现负的索引),并对该规格取余(避免出现索引出现超过矩阵规格的情况)。

由于本题涉及到的是一个二维空间,因此我们直接利用 STL 提供的模板数据结构 pair 作为 BFS 中队列的基本数据类型。下面直接给出求解本题的完整代码:

/*
    MT2241 循环空间 
    广度优先搜索(必须快读输入数据,否则会超时 3/10 的数据) 
*/ 

#include<bits/stdc++.h> 
using namespace std;

const int N = 2005;
// 存放矩阵的二维表,对应的访问标记表(到该点的最短路径)
int matrix[N][N], vis[N][N];
// 矩阵规格,起始点坐标 
int n, startX, startY;
// 当前位置和下一个状态所处位置
pair<int, int> curPoint, nextPoint;
// 四种行走方式(上、下、左、右) 
int forwardX[] = {0, 0, -1, 1};
int forwardY[] = {-1, 1, 0, 0};

// 录入矩阵信息 
void getMatrix()
{
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++){
            cin>>matrix[i][j];
            if(matrix[i][j] == 2){
                startX = i;
                startY = j; 
            }
        }
}

// 获取从指定位置出发到各点的最短路径长度 
void BFS(int x, int y)
{
    // 初始化访问标记表
    memset(vis, -1, sizeof(vis));
    // 初始化队列 
    queue<pair<int,int> > q;
    // 创建当前的点位置
    curPoint = make_pair(x,y); 
    // 入队列 
    q.push(curPoint);
    // 重置访问标记 
    vis[x][y] = 0;
    // 广度优先搜索
    while(!q.empty()){
        // 取出当前队头元素 
        curPoint = q.front();
        // 队头元素出队列
        q.pop();
        // 向四个方向行走 
        for(int i=0; i<4; i++){
            // 新位置 
            nextPoint = make_pair((curPoint.first+forwardX[i]+n) % n, 
                (curPoint.second+forwardY[i]+n) % n);
            // 如果新位置未被访问过且可行走,则更新其值
            if(vis[nextPoint.first][nextPoint.second] < 0 && matrix[nextPoint.first][nextPoint.second] == 1){
                vis[nextPoint.first][nextPoint.second] = vis[curPoint.first][curPoint.second] + 1; 
                // 入队列
                q.push(nextPoint);
            }
        }
    }
    // 整个广度优先搜索结束后,剩余所有尚未被访问的位置将无法到达
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
            if(vis[i][j] < 0)
                 vis[i][j] = 0;
}

// 输出最短路径长度矩阵 
void printPathLength()
{
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++)
            cout<<vis[i][j]<<" ";
        cout<<endl;
    } 
} 

int main( )
{
    // 快读输入数据 
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    // 录入数据 
    cin>>n;
    getMatrix();
    // 寻找从指定点出发的最短路径 
    BFS(startX, startY);
    // 输出指定点到所有点的最短路径长度
    printPathLength(); 
    return 0;
}


BD202303 第五维度

难度:星耀    时间限制:1秒    占用内存:64M
题目描述

零维是点,点动成线;
一维是线,线动成面;
二维是面,面动成体;
三维是体,体动成史;
四维是史,史动???
现在人类企图理解第五维度。
小度是第五维度的一位智者。一天,小度发现人类的许多科学家在试图理解第五维度,人类是四维生物,若是他们理解了第五维度,很可能也会到来第五维度的空间,这显然是小度不愿意看到的(毕竟哪里都有人口数量的问题….)所以小度希望他们尽可能晚的理解第五维度,因此,小度用更高维度的视角把所有人类中在理解第五维的科学家都看到了,而这些科学家的智商会不一样,所以他们的理解速度 V i V_i Vi 也会不一样;并且,他们开始理解的时间点 S i S_i Si 也不一样。理解速度 V i V_i Vi 描述为每过单位时间可获得 V i V_i Vi 个单位理解力,也就是说在 S i + 1 S_i+1 Si+1 的时间点该科学家会第一次贡献 V i V_i Vi 的理解力。我们定义理解力总数超过 m m m 时理解了第五维度。 小度因为维度更高,可以使用时间悖论来给人类一次重大的打击,小度可以让任意一位科学家在任意一个时间点消失,所以他接下来的理解不会继续;而且人类不会记得他,所以他之前的贡献会消失。因为小度能力有限,所以小度只能使用一次暂时悖论。

现在求在尽可能晚的情况下,人类理解第五维度的最早时间点。时间点初始为 0,但显然,没有科学家能够在 0 时刻有贡献。

格式

输入格式:第一行给出一个整数 n n n 和一个整数 m m m,表示有 n n n 个科学家,在理解力总数超过 m m m 时理解了第五维度;
     第二行至第 n + 1 n+1 n+1 行:每行两个整数 S i S_i Si V i V_i Vi
     对于 100% 的数据: 1 ≤ n ≤ 10 5 , m ≤ 2 × 10 9 , 0 ≤ S i ≤ 2 × 10 9 , 0 ≤ V i ≤ 10 3 1\le n\le{10}^5,m\le2\times{10}^9,0\le S_i\le2\times{10}^9,0\le V_i\le{10}^3 1n105m2×1090Si2×1090Vi103
输出格式:一行,包含一个整数 T T T 表示在尽可能晚的情况下,人类理解第五维度的最早时间点。若人类永远无法理解第五维度,则输出 -1

样例 1

输入:
3 10
0 1
4 6
5 1

输出:

8

样例 2

输入:
3 10
0 0
4 0
5 1

输出:

-1


备注

对于第一个样例,使得   S i = 4 , V i = 6 {\ S}_i=4,V_i=6  Si=4Vi=6 的科学家消失,则每个时刻总共理解力为:0 1 2 3 4 5 7 9 11,在时刻 8 超过 m = 10 m=10 m=10,因此输出 8;对于第二个样例,人类永远无法理解第五维度,因此输出 -1


相关知识点:贪心


题解


首先对本题的意思进行一个简化:输入 n n n 个科学家开始理解第五维度的时间点   S i {\ S}_i  Si 以及其单位时间能得到的理解力 V i V_i Vi (均为非负整数),那么随着时间的推移,全部科学家的总理解力肯定是不断增加的。一旦总理解力达到了 m m m ,则认为人类能理解第五维度。但是,现在有一个具有上帝视角的人,他总能找到在这些科学家中具有最高理解力的那位并将其从抹除(则他的理解力也将消失),那么这时候人类还能理解第五维度么?如果能,则输出在这样的前提下人类理解第五维度的最早时间;否则输出 -1。

本题中, m m m 的最大取值为 2 × 10 9 2\times{10}^9 2×109 ,那么在极限情况下(只有一个科学家且   S i = 0 ,   V i = 1 {\ S}_i=0,\ V_i=1  Si=0, Vi=1)的最长时间也是 2 × 10 9 2\times{10}^9 2×109 。可以看出,如果直接枚举时间线算出人类的总理解力,并在抹除具有最高理解力的人后判断与 m m m 的大小关系是极易超时的。在这种情况下,一定要敏锐地想到二分法查找。

对于每一次查找的时间 T T T,可采取下式求解全部人类的总理解力:

for(int i=0; i<n; i++){
        if(T > S[i]){
            // 累加
            sum_comp += ((long long)T - S[i]) * V[i];
        }
}

注意,题目要求在尽可能晚的情况下,人类理解第五维度的最早时间点。而尽可能晚,就意味着每次都要抹除此刻对人类理解力共享最大的科学家。为此,我们可以在求全部人类总理解力的同时,记录其中的最大理解力,并在最后减去该值即可,于是有:

// 判断在指定时间下,人类能否理解第五维度
bool check(int T)
{
    // 在指定时间下人类的理解力总和、这些理解力中的最大值 
    long long sum_comp = 0, max_comp = 0, tmp;
    // 计算所有人的理解力总和,并找到其中的最大值
    for(int i=0; i<n; i++){
        if(T > S[i]){
            // 计算当前第 i 个人的获取的理解力 
            tmp = ((long long)T - S[i]) * V[i];
            // 累加
            sum_comp += tmp;
            // 找出具有最大贡献的理解力 
            max_comp = max(max_comp, tmp);
        }
    }
    // 要求尽可能晚的情况下,那就把具有最大共享的理解力去除即可 
    return (sum_comp - max_comp > m);
}

下面给出基于以上思路得到的求解本题的完整代码:

/*
    BD202303 第五维度 
    贪心、二分法
*/ 

#include<bits/stdc++.h> 
using namespace std;

const int N = 1e5+5;
// 各科学家的理解力起始数组、单位时间增长数组 
int S[N], V[N];
// 科学家数量和需要理解五维空间的总理解力
int n, m; 

// 判断在指定时间下,人类能否理解第五维度
bool check(int T)
{
    // 在指定时间下人类的理解力总和、这些理解力中的最大值 
    long long sum_comp = 0, max_comp = 0, tmp;
    // 计算所有人的理解力总和,并找到其中的最大值
    for(int i=0; i<n; i++){
        if(T > S[i]){
            // 计算当前第 i 个人的获取的理解力 
            tmp = ((long long)T - S[i]) * V[i];
            // 累加
            sum_comp += tmp;
            // 找出具有最大贡献的理解力 
            max_comp = max(max_comp, tmp);
        }
    }
    // 要求尽可能晚的情况下,那就把具有最大共享的理解力去除即可 
    return (sum_comp - max_comp > m);
}

// 二分查找使科学家能理解的最早时间 
int BinarySearch()
{
    // 能理解的极限情况下,只有 1 个科学家,理解力最小为 1,则最长的时间为 2e9
    long long l = 1, r = 2e9;
    int ans = -1;
    // 二分查找 
    while(l < r){
        int mid = l+r >> 1;
        // 判断该时间下(尽可能晚),人类能否理解第五维度
        if(check(mid)){
            r = mid;
            ans = mid; 
        }else{
            l = mid + 1;
        } 
    }
    return ans;
}

int main( )
{
    // 录入数据 
    cin>>n>>m;
    for(int i=0; i<n; i++)
        cin>>S[i]>>V[i];
    // 输出使科学家能理解的最早时间
    cout<<BinarySearch()<<endl;
    return 0;
}

END


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1147281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Zabbix监控oxidized备份状态

Zabbix监控oxidized备份状态 原理是利用oxidized的hooks功能调用zabbix_sender推送数据给zabbix_server 参考 https://cloud.tencent.com/developer/article/1657025 https://github.com/clontarfx/zabbix-template-oxidized https://github.com/ytti/oxidized/blob/master/…

Redis原理-IO模型和持久化

高性能IO模型 为什么单线程Redis能那么快 一方面&#xff0c;Redis 的大部分操作在内存上完成&#xff0c;再加上它采用了高效的数据结构&#xff0c;例如哈希表和跳表&#xff0c;这是它实现高性能的一个重要原因。另一方面&#xff0c;就是 Redis 采用了多路复用机制&#…

Arcmap制图绘制显著性区域

类似于下图这种&#xff0c;为分析结果添加显著性区域&#xff0c;该如何实现呢&#xff1f; 实现方式多种多样&#xff0c;比如&#xff1a; 1、代码。Python、R、Matlab都有实现方式&#xff0c;但是绘制一幅优美的地图&#xff0c;用代码绘制&#xff0c;需要添加很多控制语…

广东木模板批发,建筑桥梁工程专用组合木模板

作为广东地区的木模板批发商&#xff0c;我们致力于为建筑行业提供高品质的木模板产品。在众多产品中&#xff0c;我们特别推荐我们的建筑桥梁工程专用组合木模板&#xff0c;为桥梁工程提供卓越的支持和出色的性能。 我们的组合木模板是专为桥梁工程设计的&#xff0c;以满足对…

苍穹外卖-day04-套餐管理

1. 新增套餐 1.1 需求分析和设计 产品原型&#xff1a; 业务规则&#xff1a; 套餐名称唯一套餐必须属于某个分类套餐必须包含菜品名称、分类、价格、图片为必填项添加菜品窗口需要根据分类类型来展示菜品新增的套餐默认为停售状态 接口设计&#xff08;共涉及到4个接口&am…

Redis(windows+Linux)安装及入门

一、概述 Redis是什么&#xff1f; Redis(Remote Dictionary Server)&#xff0c;即远程字典服务 Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数…

嵌入式学习笔记(65)野指针问题

3.3.1.神马是野指针&#xff1f;哪里来的&#xff1f;有什么危害&#xff1f; 我的理解&#xff1a;野指针就是定义了指针没有给指针赋值。 (1)野指针&#xff0c;就是指针指向的位置是不可知的&#xff08;随机的、不正确的、没有明确限制的&#xff09; (2)野指针很可能触…

傅立叶级数的意义--傅立叶级数是怎么来的

写这篇文章的起因是14年有道题目&#xff1a; 本题实质上是考察傅立叶级数的意义&#xff0c;因此要求扩大为不能只拘泥于傅里叶级数的计算相关问题&#xff0c;故作此篇。 一、课本上的内容 傅立叶级数&#xff1a; 设函数 f ( x ) f(x) f(x)是周期为 2 l 2l 2l的周期函数&…

Redis队列Stream

1 缘起 项目中处理文件的场景&#xff1a; 将文件处理请求放入队列&#xff0c; 一方面&#xff0c;缓解服务器文件处理压力&#xff1b; 另一方面&#xff0c;可以根据文件大小拆分到不同的队列&#xff0c;提高文件处理效率。 这是Java开发组Leader佳汇提出的文件处理方案&a…

了解性能测试流程

性能测试概念 我们经常看到的性能测试概念&#xff0c;有人或称之为性能策略&#xff0c;或称之为性能方法&#xff0c;或称之为性能场景分类&#xff0c;大概可以看到性能测试、负载测试、压力测试、强度测试等一堆专有名词的解释。 针对这些概念&#xff0c;我不知道你看到…

【数据分析】上市公司半年报数据分析

前言 前文介绍过使用网络技术获取上市公司半年报数据的方法&#xff0c;本文将对获取到的数据进行简要的数据分析。 获取数据的代码介绍在下面的两篇文章中 【java爬虫】使用selenium获取某交易所公司半年报数据-CSDN博客 【java爬虫】公司半年报数据展示-CSDN博客 全量数…

【uniapp】JavaScript基础学习-20231027

今天有找到一个比较好的网站 https://www.w3school.com.cn/js/index.asp 介绍也全面&#xff0c;内容也比较多。我觉得把最基本的语法看看&#xff0c;然后可以上手写代码了。其他的就是需要靠长期的学习和积累了。 基础语法的使用&#xff1a; 1、定义一个变量 2、对变量赋值 …

拿到 phpMyAdmin 如何获取权限

文章目录 拿到 phpMyAdmin 如何获取权限1. outfile 写一句话木马2. general_log_file 写一句话木马 拿到 phpMyAdmin 如何获取权限 1. outfile 写一句话木马 尝试使用SQL注入写文件的方式&#xff0c;执行 outfile 语句写入一句话木马。 select "<?php eval($_REQU…

10.29数算小复习(选择题细节,二路归并,结构体排序)

排序、复杂度、细节&#xff08;选择题&#xff0c;判断题&#xff09; 对于一个已经排好序的序列&#xff0c;直接插入排序的复杂度是O(n)&#xff0c;而归并排序的复杂度是O(nlogn)。这时候归并排序就不比直接插入排序速度快了。 归并排序的最好、最坏、平均时间都是O(nlogn)…

【Spring】Spring MVC请求响应

文章目录 1. 请求1.1 传递单个参数1.2 传递多个参数1.3 传递对象1.4 后端参数重命名1.5 传递数组1.6 传递集合1.7 传递JSON对象1.8 获取URL中参数1.9 上传⽂件1.10 获得Cookie1.11 获得Session1.12 获得Header 2. 响应2.1 返回静态界面2.2 返回数据2.3 返回HTML代码片段2.4 返回…

微机原理:汇编语言程序设计

文章目录 一、汇编格式1、文字简述2、代码表述 二、汇编语言结构说明1、方式选择伪指令2、段定义语句3、段约定语句4、汇编结束语句5、返回DOS语句 三、实例1、例子2、汇编语言程序开发过程 四、功能调用DOS功能调用1、功能号01H2、功能号02H3、功能号09H4、功能号0AH5、举例 B…

操作系统——二级页表(王道视频p50)

1.总体概述&#xff1a; 2.二级页表的工作原理——如何实现一个逻辑地址到物理地址的转换 具体工作原理(有一个地方没有弄明白——就是到底是如何通过顶级页表找到 二级页表项的&#xff1f;)

el-input 给icon图标绑定点击事件

选择suffix-icon&#xff0c;添加点击事件 <temeplate><el-form-item :label"$t(company[Company address])" prop"address"><el-input v-model"enterpriseForm.address"><i slot"suffix" class"el-icon-m…

联邦学习与推荐系统

[Personalized Federated Recommendation via Joint Representation Learning, User Clustering, and Model Adaptation] (https://dl.acm.org/doi/abs/10.1145/3511808.3557668) CIKM2022(CCF-B) 论文精读 Abstract 联邦推荐的背景&#xff1a;联邦推荐使用联邦学习技术在推…

四十、【进阶】索引失效情况2

1、or的使用 在使用索引查询时&#xff0c;如果使用了or&#xff0c;会出现以下情况&#xff1a; &#xff08;情况一&#xff09;or左边是索引查询&#xff0c;or右边不是索引查询 结果&#xff1a;索引查询失效 &#xff08;情况二&#xff09;or左边不是索引查询&#x…