2023蓝桥杯省模拟赛附近最小

news2024/10/7 10:20:04

2023蓝桥杯省模拟赛附近最小

在这里插入图片描述

这个题算是一个经典的数据结构入门题了,写了几个解法水一篇文章

map维护

时间复杂度nlgn,但是常数比较大,所以只能过90%数据

#include <iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll mod = 1e9 + 7;
int a[N];
void solve()
{
    int n, k;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    cin >> k;
    map<int, int>mp;
    int l = 1, r = min(k + 1, n);
    for (int i = 1; i <= r; i++)
        mp[a[i]]++;
    cout << mp.begin()->first;
    for (int i = 2; i <= n; i++) {
        int l1 = max(1, i - k), r1 = min(n, k + i);
        if (l1 > l)
            mp[a[l]]--;
        if (r1 > r)
            mp[a[r1]]++;
        if (mp[a[l]] == 0)
            mp.erase(a[l]);
        l = l1, r = r1;
        cout << " " << mp.begin()->first;
    }
    cout << '\n';
}
int  main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

单调队列

这算是题解区看到的最多的解法了,刚开始也没往这方面想,直接无脑贴了个线段树上去

代码里面有注释

时间复杂度是线性的,但是deque的常数是stl里面都算很大的,所以也比较慢,可以尝试用数组模拟deque

#include<iostream>
#include<deque>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
int a[N];
int main()
{
    int n, k;
    cin >> n;
    deque<int> dq;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    cin >> k;
    for (int i = n + 1; i <= n + k; i++)
        a[i] = 2 * N;
    for (int i = 1; i <= n + k; i++)
    {
        while (!dq.empty() && a[dq.back()] > a[i])
            dq.pop_back();
        dq.push_back(i);
        while (i - 2 * k > dq.front())
            dq.pop_front();
        if (i > k)  cout << a[dq.front()] << " ";
    }
    return 0;
}
//为了方便判断范围所以将数组的下标索引加入队列。
// //使用双端队列实现滑动窗口,窗口每次向后移动,若新的数字比队尾大,
//直接进入队列, 比队尾小,需要弹出队列中所有比新的数字小的值,
//保证队头保存的是当前窗口中最小的值
//通过维护一个单调递增的队列,可以得到一个滑动窗口的最小值,
//并将他加入队列。例如窗口[7, 4, 3] 的最小值就是 3 
//,那么对于题目要求的一定范围我们只需要每次输出前判断队首是否超过范围就行了,
//如果超过范围就将队首弹出,那么队列就只剩下[3] 了。

树状数组

把窗口中的数投到长度为1e6的数轴上,每投影一个数在数轴对应位置+1,然后转换成了求第一个数轴的前缀和大于等于1的点的位置,二分即可,当然这个前缀和也可以用线段树维护

这个解法的局限性在于a[i]的值域,如果值域过大,比如1e18,那肯定开不下这么大的数组,就需要离散化一下了

下面提供非离散化和离散化的代码

非离散化

#include <iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll mod = 1e9 + 7;
int tree[N], a[N];
int lowbit(int x) {
    return x & (-x);
}
int sum(int x) {
    int ans = 0;
    while (x) {
        ans += tree[x];
        x -= lowbit(x);
    }
    return ans;
}
void change(int x, int p) {
    while (p<N) {
        tree[p] += x;
        p += lowbit(p);
    }
}
void solve()
{
    int n,k;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    int mi = 0x3f3f3f3f;
    cin >> k;
    int l = 1, r = min(k + 1, n),x=0x3f3f3f3f;
    for (int i = 1; i <= r; i++)
        change(1, a[i]),mi=min(a[i],mi);
    cout << mi;
    for (int i = 2; i <= n; i++) {
        int l1 = max(1, i - k), r1 = min(n, k + i);
        if (l1 > l)
            change(-1, a[l]);
        if (r1 > r)
            change(1, a[r1]);
        int x = 1, y = 1e6 + 1;
        while (x < y) {
            int mid = x + y >> 1;
            if (sum(mid) >= 1)
                y = mid;
            else
                x = mid + 1;
        }
        l = l1, r = r1;
        cout << " " << y;
    }
    cout << '\n';
}
int  main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

离散化

#include <iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll mod = 1e9 + 7;
int tree[N], a[N],b[N];
int len = 0, n, k;
int lowbit(int x) {
    return x & (-x);
}
int sum(int x) {
    int ans = 0;
    while (x) {
        ans += tree[x];
        x -= lowbit(x);
    }
    return ans;
}
void change(int x, int p) {
    while (p<=n) {
        tree[p] += x;
        p += lowbit(p);
    }
}
int serach(int x) {
    int l = 1, r = len + 1;
    while (l < r) {
        int mid = l + r >> 1;
        if (b[mid] == x)
            return mid;
        else if (b[mid] < x)
            l = mid + 1;
        else
            r = mid;
    }
    return r;
}
void solve()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i],b[i]=a[i];
    int mi = 0x3f3f3f3f;
    cin >> k;
    sort(b + 1, b + n + 1);
    for ( int j = 1; j <= n; j++) {
        if (b[j] != b[j-1])
            b[++len] = b[j];
    }
    int l = 1, r = min(k + 1, n),x=0x3f3f3f3f;
    for (int i = 1; i <= r; i++)
        change(1, serach(a[i])),mi=min(a[i],mi);
    cout << mi;
    for (int i = 2; i <= n; i++) {
        int l1 = max(1, i - k), r1 = min(n, k + i);
        if (l1 > l) {
            change(-1, serach(a[l]));
        }
        if (r1 > r)
            change(1, serach(a[r1]));
        int x = 1, y = len + 1;
        while (x < y) {
            int mid = x + y >> 1;
            if (sum(mid) >= 1)
                y = mid;
            else
                x = mid + 1;
        }
        l = l1, r = r1;
        cout << " " << b[y];
    }
    cout << '\n';
}
int  main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

类似题

力扣342周赛也考了个类似的题,也可以用树状数组求解

在这里插入图片描述

class Solution {
public:
int tree[110];
int lowbit(int x){
    return x&-x;
}
int sum(int x){
    int ans=0;
    while(x){
        ans+=tree[x];
        x-=lowbit(x);
    }
    return ans;
}
void change(int pos,int x){
    while(pos<=105){
        tree[pos]+=x;
        pos+=lowbit(pos);
    }
}
    vector<int> getSubarrayBeauty(vector<int>& a, int k, int x) {
        vector<int>ans;
        for(int i=0;i<k;i++)
        change(a[i]+51,1);
        int l=1,r=105;
        while(l<r){
            int mid=l+r>>1;
            if(sum(mid)>=x)
            r=mid;
            else
            l=mid+1;
        }
        if(r-51<0)
        ans.push_back(r-51);
        else 
        ans.push_back(0);
        for(int i=1;i+k-1<a.size();i++){
            change(a[i-1]+51,-1);
            change(a[i+k-1]+51,1);
            l=1,r=105;
        while(l<r){
            int mid=l+r>>1;
            if(sum(mid)>=x)
            r=mid;
            else
            l=mid+1;
        }
        if(r-51<0)
        ans.push_back(r-51);
        else 
        ans.push_back(0);
        }
        return ans;
    }
};

ST表

st表最经典的应用就是求解静态rmq问题了

下面用倍增跳表求解

#include <iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll mod = 1e9 + 7;
int st[N][21],lg2[N];
void solve()
{
    int n,k;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> st[i][0];
    for (int i = 2; i <= n; i++)
        lg2[i] = lg2[i / 2] + 1;
    cin >> k;
    for (int i = 1; (1 << i) <= n; i++) {
        for (int j = 1; j + (1 << i) - 1 <= n; j++)
            st[j][i] = min(st[j][i - 1], st[j + (1 << (i - 1))][i - 1]);
    }
    for (int i = 1; i <= n; i++) {
        int l = max(1, i - k), r = min(n, k + i);
        int len = r - l + 1,mi=0x3f3f3f3f;
        //cout << i << '\n';
        while (len) {
            mi = min(mi, st[l][lg2[len]]);
            l += (1 << lg2[len]);
            len -= (1 << lg2[len]);
        }
        cout << mi;
        if (i < n)
            cout << ' ';
        else
            cout << '\n';
    }
    //cout << '\n';
}
int  main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

线段树

线段树无脑维护就行了,只需要写查询

#include <iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int a[N];
struct tnode {
    int l, r;
    int sum;
};
struct Segment_Tree
{
    tnode t[4 * N];
    void build(int root, int l, int r, int* A)
    {
        t[root].l = l, t[root].r = r;
        if (l == r)
            t[root].sum = A[l];
        else {
            int ch = root << 1, mid = l + r >> 1;
            build(ch, l, mid, A);
            build(ch + 1, mid + 1, r, A);
            t[root].sum = min(t[ch].sum , t[ch + 1].sum);
        }
    }
    int query_min(int root, int l, int r)
    {
        if (l == t[root].l && r == t[root].r)
            return t[root].sum;
        int mid = t[root].l + t[root].r >> 1;
        if (r <= mid)
            return query_min(root << 1, l, r);
        else if (l > mid)
            return query_min(root << 1 | 1, l, r);
        else
            return min(query_min(root << 1, l, mid) , query_min(root << 1 | 1, mid + 1, r));
    }
};
Segment_Tree st;
void solve()
{
    int n,k;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    cin >> k;
    st.build(1, 1, n, a);
    for (int i = 1; i <= n; i++) {
        int l = max(1, i - k), r = min(n, k + i);
        if (i < n)
            cout << st.query_min(1, l, r) << ' ';
        else
            cout << st.query_min(1, l, r) << '\n';
    }
}
int  main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
    //    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

分块

这题分块有可能可以过但也有可能过不了,取决于块大小的取值,试了不少的块取值还是没过最后一组样例

下面的代码块取得比较小,但是如果块大小取值改一下,数据再强一些,就不只是运行超时了,还会出现答案错误,可以自己去想一想然后试一下,这份代码运气好,所以只运行超时了

#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<cmath> 
using namespace std;
const int N = 1e6 + 10;
int a[N], b[N], mi[N], bg[N], ed[N], pos[N];
void slove() {
    int n, k;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    cin >> k;
    int block = sqrt(k), t;
    t = n / block;
    if (n % block)
        t++;
    for (int i = 1; i <= t; i++)
        bg[i] = block * (i - 1) + 1, ed[i] = block * i;
    ed[t] = n;
    for (int i = 1; i <= n; i++)
        pos[i] = (i - 1) / block + 1;
    for (int i = 1; i <= t; i++) {
        mi[i] = 0x3f3f3f3f;
        for (int j = bg[i]; j <= ed[i]; j++)
            mi[i] = min(a[j], mi[i]);
    }
    for (int i = 1; i <= n; i++) {
        int l = max(1, i - k), r = min(n, k + i), x, y;
        if (l > bg[pos[l]])
            x = pos[l] + 1;
        else
            x = pos[l];
        if (r < ed[pos[r]])
            y = pos[r] - 1;
        else
            y = pos[r];
        int ans = 0x3f3f3f3f;
        for (int i = l; i < bg[x]; i++)
            ans = min(a[i], ans);
        for (int i = x; i <= y; i++)
            ans = min(mi[i], ans);
        for (int i = bg[y] + 1; i <= r; i++)
            ans = min(a[i], ans);
        cout << ans;
        if (i < n)
            cout << ' ';
        else
            cout << '\n';
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T;
    T = 1;
    //cin >> T;
    while (T--) {
        slove();
    }
    return 0;
}

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

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

相关文章

卖房子真是稳赚不赔

上面是一段很长的语音&#xff0c;对话是用的我们河池的桂柳话&#xff0c;不过桂柳话和普通话有很多相识之处&#xff0c;理解起来并不困难。 大概的意思是 A公司要给员工一批福利房&#xff0c;然后就让开发商来竞标&#xff0c;竞标的时候开发商就会说明清楚到时候给员工的房…

关于stl容器的迭代器失效问题

场景 在项目中使用stl容器的时候&#xff0c;多线程环境下出错&#xff0c;调试很久发现问题是使用容器的时候由于容器扩容导致的线程不安全&#xff0c;还有扩容导致的迭代器失效问题&#xff0c;于是就想着把迭代器失效的问题总结一下。 场景重现1   我在项目开发中使用ve…

【AI帮我写代码,上班摸鱼不是梦】如何调教ChatGPT,让它帮我写程序。

最近发现磁盘空间严重不足&#xff0c;都弹窗提示我了&#xff1a; 想想看到底哪个文件夹占的空间比较大&#xff0c;好做针对性的删除和清理。奈何Windows系统没有查看文件夹大小的工具&#xff0c;只能鼠标放在某个文件夹上&#xff0c;等提示&#xff1a; AI时代都来临了&am…

AttributeError: ‘ChatGLMConfig‘ object has no attribute ‘quantization_bit‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

STM32 产生随机数方式

STM32 产生随机数方式 C语言的stdlib.h库里的srand(unsigned seed)和rand(void)函数&#xff0c;可以配合产生伪随机数。其中srand(seed)产生算法种子&#xff0c;再由rand()通过算法产生随机数&#xff0c;产生的随机数在宏定义RAND_MAX范围内。如果seed不变&#xff0c;则产…

测试从未如此简单:接口自动化测试Python脚本实现

目录 摘要 步骤1&#xff1a;安装依赖项 步骤2&#xff1a;编写测试脚本 步骤3&#xff1a;运行测试 结论 摘要 自动化测试是现代软件开发过程中的重要环节。在许多情况下&#xff0c;特别是在web应用程序和移动应用程序中&#xff0c;接口自动化测试是其基础。下面就来介绍一…

嵌入式就业怎么样?

嵌入式就业怎么样? 现在的IT行业,嵌入式是大热门&#xff0c;下面也要来给大家介绍下学习嵌入式之后的发展以及就业怎么样。 首先是好找工作。嵌入式人才目前是处于供不应求的状态中&#xff0c;据权威统计机构统计在所有软件开发类人才的需求中&#xff0c;对嵌入式工程师的…

详解树与二叉树的概念,结构,及实现(上篇)

目录 一&#xff0c; 树 1.2 树的相关概念 1.3 树的表示 1.4 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 二&#xff0c; 二叉树 2.1二叉树概念 三&#xff0c;特殊的二叉树 1. 满二叉树 2. 完全二叉树 3. 1 二叉树的性质 3. 2 二叉树的存储…

北邮22信通:二叉树层序遍历的两种方法首发模板类交互

北邮22信通一枚~ 跟随课程进度每周更新数据结构与算法的代码和文章 持续关注作者 解锁更多邮苑信通专属代码~ 获取更多文章 请访问专栏~ 北邮22信通_青山如墨雨如画的博客-CSDN博客 目录 一.总纲 二.用队列存储 2.1用模板类实现队列 2.1.1核心思路&#xff1a; …

FL Studio电音编曲软件V21中文完整版 安装下载教程

目前水果软件最版本是FL Studio 21&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音乐突破想象力的限制。喜欢音乐制作的小伙伴千万不要错过这个功能强大&#xff0c;安装便捷的音乐软件哦&#xff01;…

PTA L2-045 堆宝塔 (25 分)

堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小&#xff0c;按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺序抓到的。聪明宝宝采取的策略如下&#xff1a; 首先准备两根柱子&#xff0c;一根 A 柱串宝塔&#xff0c;一根 B 柱用于临时叠放。把第 1 块彩虹圈…

掌握ChatGPT:全面指南和GPT-3.5与GPT-Plus的对比分析

在人工智能领域&#xff0c;最近的一大重磅炸弹是OpenAI发布了GPT-4架构下的ChatGPT。这款先进的自然语言处理模型已经引起了很多关注&#xff0c;让我们来深入了解怎么使用这个强大的工具&#xff0c;以及比较GPT-3.5与GPT-Plus的差异。 什么是ChatGPT&#xff1f; ChatGPT是…

JavaScript经典教程(三)-- JavaScript -- 基础数据类型详解

183&#xff1a;基础数据类型详解 1、复习 1、全局变量&#xff1a; 依托于window环境下的的变量。 在window大环境下&#xff08;即最外层&#xff09;申明的变量a&#xff0c;即为全局变量。 2、window&#xff1a; window下的变量为全局变量。 window可省略。 3、作用域…

021 - C++ 构造函数

我们继续学习 C 的面向对象编程&#xff0c;本期主要是讲其中的 构造函数。 什么是构造函数呢&#xff1f; 构造函数基本上是一种特殊类型的方法&#xff0c;它在每次实例化对象时运行。 我们直接来看一个例子吧。 例子时间 我们将要通过创建一个 Entity 类来深入了解这个…

vscode python3.6配置pcl点云库 obj3d模型转pcd点云图

配置vscode python3.6的环境我就跳过了,网上都有 1.下载PCL1.9 github:pcl-1.9.1 百度云:PCL-1.9.1-AllInOne-msvc2017-win64提取码adcx 2.安装硬盘任意位置,我是E盘,在安装过程中会弹出openni的安装提示,将它安装路径选择在E:\PCL 1.9.1\3rdParty\OpenNI2,等待安装完成 3.…

.netCHATING 10.4 for NET6-7.0-Crack

.NET 6.0图表支持--dotnetcharting .netCHATING 10.4添加了.NET 6.0图表nuget包和.NET 6.0图表示例包&#xff08;需要Visual Studio 2022&#xff09;&#xff0c;.NET 5是.NET Core 3.1和.NET Framework 4.8的继任者&#xff0c;旨在为.NET开发人员提供新的跨平台开发体验。…

Mysql列的类型定义(字符串类型)

文章目录 一、CHAR 类型和 VARCHAR 类型 1.字符串字符(M)2.实战类型二、TEXT 类型 1.类型表2.特别注意3.实战建议4.实战练习三、ENUM 和 SET 类型 1.ENUM类型2.SET类型总结 一、CHAR 类型和 VARCHAR 类型 CHAR类型和VARCHAR类型都在创建表时指定了最大长度&#xff0c;其基本形…

Java版工程行业管理系统源码-专业的工程管理软件-提供一站式服务

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

对数据结构的初步认识

前言: 牛牛开始更新数据结构的知识了.本专栏后续会分享用c语言实现顺序表,链表,二叉树,栈和队列,排序算法等相关知识,欢迎友友们互相学习,可以私信互相讨论哦! &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&a…

拿下多家车企定点!4D毫米波雷达「域」系统首发出道

从1R、2R、3R到整车360感知方案&#xff0c;毫米波雷达的前装市场需求量依然保持着快速增长的态势。 高工智能汽车研究院监测数据显示&#xff0c;2022年中国市场&#xff08;不含进出口&#xff09;前装标配搭载ADAS毫米波雷达&#xff08;前向后向盲区&#xff09;交付1795.…