E. Exposition

news2025/3/14 1:16:41

题目链接:Problem - E - Codeforces

题目大意: 给你一个长度为n的序列,和一个整数k.现让找出所有连续的最长子区间, 其子区间的条件是:在区间里最大值减去最小值之差要小于 k .

输入:

输入数据的第一行包含两个用空格隔开的整数 n ( 1 ≤ n ≤ 1e5 )和 k ( 0 ≤ k ≤ 1e6 )

第二行包含 n 个整数,以空格分隔。每个数字 ai ( 1 ≤ ai ≤ 1e6 ).

输出:

在输出数据的第一行打印两个数字 a 和 b (用空格隔开),其中 a是每个区间的长度。b是个数

在接下来的 b 行中,每行打印两个整数,中间用空格隔开,起始位置与终点位置。

具体题目描述见链接。

方法: 线段树,ST表, 二分

1.由于题目要求是要,让最大值与最小值做差运算小于k. 所以不难想到用一个特殊的数据结构去维护最大值于最小值。

2.看数据范围 1e5, 暴力求解区间的满足情况是不行的, 考虑使用其它算法。 当发现若只有一个数时,那它的最大值减去最小值就为0(也就最小的情况)。区间覆盖的越广,差值可能就越大,有单调性。考虑二分。

3.二分: 通过枚举左边界[1,n], 然后通过最大值二分找出相应的右边界, 统计此时的区间最大值。然后使用map将区间长度一致的分在一起,

4.二分时,要查询[i, mid](代码里), 就要使用ST表或者线段树维护的最值。 此处的最大值二分见代码。

先贴ST表做法:

二分关键代码:

int mxx = 0; //记录最长的区间
    map<int, vector<pair<int,int>>> mp;//统计答案
    for(int i=1; i<=n; i++) {
        int l = i;
        int r = n;
        int dl = i;
        while(l<=r) { //二分右边界
            int mid = (l+r) >> 1;
            if(go(i,mid)<=k) { // go()函数查询的是差值,注意 i, 到mid
                dl = mid;  //满足, 看是否还可以变长,最值二分
                l = mid+1;
            }else{
                r = mid-1;
            }
        }
        mp[dl-i+1].push_back({i,dl});// 分区间
        mxx = max(mxx, dl-i+1); // 找最长的
    }

ST表完整代码:

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

using i64 = long long;
using i128 = __int128;
using ui64 = unsigned long long;

struct ST{
    vector<vector<int>> data;
    vector<int> lg2;
    int n;

    ST(){}
    ST(int n){
        innt(n);
    }

    void innt(int n){
        this->n = n;
        data.resize(n+1, vector<int>(32));
        lg2.resize(n+1);
        lg2[0] = -1;
        for(int i=1; i<=n; i++) {
            lg2[i] = lg2[i>>1] + 1;
        }
    }

    int gcd(int a, int b){
        return b==0? a : gcd(b, a%b);
    }
    void buildGcd(){
        for(int p=1; p<=lg2[n]; p++) {
            for(int i=1; i + (1<<p) - 1 <= n; i++) {
                data[i][p] = gcd(data[i][p - 1], data[i + (1 << (p-1))][p-1]);
            }
        }
    }
    int queryGcd(int l, int r){
        int p = lg2[r-l+1];
        return gcd(data[l][p], data[r-(1<<p)+1][p]);
    }

    void buildMax(){
        for(int p=1; p<=lg2[n]; p++) {
            for(int i=1; i + (1<<p) - 1<=n; i++) {
                data[i][p] = max(data[i][p-1], data[i + (1<<(p-1))][p-1]);
            }
        }
    }
    int queryMax(int l, int r){
        int p = lg2[r-l+1];
        return max(data[l][p], data[r-(1<<p)+1][p]);
    }

    void buildMin(){
        for(int p=1; p<=lg2[n]; p++) {
            for(int i=1; i + (1<<p) - 1<=n; i++) {
                data[i][p] = min(data[i][p-1], data[i + (1<<(p-1))][p-1]);
            }
        }
    }
    int queryMin(int l, int r){
        int p = lg2[r-l+1];
        return min(data[l][p], data[r-(1<<p)+1][p]);
    }

    void buildAnd(){
        for(int p=1; p<=lg2[n]; p++) {
            for(int i=1; i + (1<<p) - 1<=n; i++) {
                data[i][p] = data[i][p-1] & data[i + (1<<(p-1))][p-1];
            }
        }
    }
    int queryAnd(int l, int r){
        int p = lg2[r-l+1];
        return data[l][p] & data[r-(1<<p)+1][p];
    }

    void buildOr(){
        for(int p=1; p<=lg2[n]; p++) {
            for(int i=1; i + (1<<p) - 1<=n; i++) {
                data[i][p] = data[i][p-1] | data[i + (1<<(p-1))][p-1];
            }
        }
    }
    int queryOr(int l, int r){
        int p = lg2[r-l+1];
        return data[l][p] | data[r-(1<<p)+1][p];
    }
};

ST stmi, stmx; //使用的封装好的ST表

int go(int l, int r){ //做差值运算
    return stmx.queryMax(l, r) - stmi.queryMin(l, r);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    int n, k;
    cin >> n >> k;
    stmi.innt(n), stmx.innt(n);
    for(int i=1; i<=n; i++) {
        int t;
        cin >> t;
        stmi.data[i][0] = stmx.data[i][0] = t;
    }

    stmi.buildMin();
    stmx.buildMax();//建ST表

    int mxx = 0;
    map<int, vector<pair<int,int>>> mp;
    for(int i=1; i<=n; i++) {
        int l = i;
        int r = n;
        int dl = i;
        while(l<=r) { //二分右边界
            int mid = (l+r) >> 1;
            if(go(i,mid)<=k) {
                dl = mid;
                l = mid+1;
            }else{
                r = mid-1;
            }
        }
        mp[dl-i+1].push_back({i,dl});
        mxx = max(mxx, dl-i+1);
    }

    cout << mxx << ' ' << mp[mxx].size() << "\n";
    for(auto[x, y] : mp[mxx]) {
        cout << x << " " << y << "\n";
    }
    
    return 0;
}

线段树做法, 二分方法一致。只是采用线段树维护最值了。

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

using i64 = long long;
using i128 = __int128;
using ui64 = unsigned long long;

const int N = 1e5+3;
struct Node{
    int l, r;
    int mi, mx;
}tr[N<<2]; // 开四倍
int a[N];
int n, k;

void up(int id){
    tr[id].mi = min(tr[id<<1].mi, tr[id<<1|1].mi);
    tr[id].mx = max(tr[id<<1].mx, tr[id<<1|1].mx);
}

void build(int id, int l,int r){
    tr[id].l = l;
    tr[id].r = r;
    if(l==r) {
        tr[id].mi = tr[id].mx = a[r];
        return ;
    }
    int mid = (l+r)>>1;
    build(id<<1, l, mid);
    build(id<<1|1, mid+1, r);
    up(id);
}

int query_mi(int id, int jobl, int jobr){
    if(jobl <= tr[id].l && tr[id].r<=jobr){
        return tr[id].mi;
    }
    int mid = (tr[id].l + tr[id].r) >>1;
    int res = INT_MAX;
    if(jobl <= mid) {
        res = min(res, query_mi(id<<1, jobl, jobr));
    }
    if(jobr > mid) {
        res = min(res, query_mi(id<<1 | 1, jobl, jobr));
    }
    return res;
}

int query_mx(int id, int jobl, int jobr){
    if(jobl <= tr[id].l && tr[id].r<=jobr){
        return tr[id].mx;
    }
    int mid = (tr[id].l + tr[id].r) >>1;
    int res = INT_MIN;
    if(jobl <= mid) {
        res = max(res, query_mx(id<<1, jobl, jobr));
    }
    if(jobr > mid) {
        res = max(res, query_mx(id<<1 | 1, jobl, jobr));
    }
    return res;
}

int go(int jobl, int jobr){
    return query_mx(1, jobl, jobr) - query_mi(1, jobl, jobr);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    cin >> n >> k;
    for(int i=1; i<=n; i++) {
        cin >> a[i];
    }
    map<int, vector<pair<int,int>>> mp;
    build(1, 1, n); //建树
    int mxx = 0;
    for(int i=1; i<=n; i++) {
        int l = i;
        int r = n;
        int dl = i;
        while(l<=r) {
            int mid = (l+r)>>1;
            if(go(i,mid) <= k) {
                dl = mid;
                l = mid+1;
            }else{
                r = mid-1;
            }
        }
        mxx = max(mxx, dl - i + 1);
        mp[dl-i+1].push_back({i,dl});
    }

    cout << mxx << " " << mp[mxx].size() << "\n";
    for(auto [x,y] : mp[mxx]) {
        cout << x << " " << y << "\n";
    }
    return 0;
}

欢迎大佬指正,感谢你的收看与点赞。

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

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

相关文章

unity删除了安卓打包平台,unityhub 还显示已经安装,怎么解决

解决问题地址 可能由于版本问题文章中这个我没搜到&#xff0c;应该搜Android Build Supprot

C++ Primer 参数传递

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

数据结构 day06

数据结构 day06 6. 双向链表6.3. 双向循环链表 7. 树 tree7.1. 特点7.1.1. 什么是树7.1.2. 树的特性7.1.3. 关于树的一些术语 7.2. 二叉树7.2.1. 什么是二叉树7.2.2. 二叉树的性质7.2.3. 满二叉树和完全二叉树的区别7.2.4. 二叉树的遍历&#xff08;画图&#xff09;7.2.5. 二叉…

AI编程01-生成前/后端接口对表-豆包(或Deepseek+WPS的AI

前言: 做过全栈的工程师知道,如果一个APP的项目分别是前端/后端两个团队开发的话,那么原型设计之后,通过接口文档进行开发对接是非常必要的。 传统的方法是,大家一起定义一个接口文档,然后,前端和后端的工程师进行为何,现在AI的时代,是不是通过AI能协助呢,显然可以…

01什么是DevOps

在日常开发中&#xff0c;运维人员主要负责跟生产环境打交道&#xff0c;开发和测试&#xff0c;不去操作生产环境的内容&#xff0c;生产环境由运维人员操作&#xff0c;这里面包含了环境的搭建、系统监控、故障的转移&#xff0c;还有软件的维护等内容。 当一个项目开发完毕&…

力扣100. 相同的树(利用分解思想解决)

Problem: 100. 相同的树 文章目录 题目描述思路Code 题目描述 思路 题目要求判断两个二叉树是否完全相同&#xff0c;而此要求可以利用问题分解的思想解决&#xff0c;即判断当前节点的左右子树是否完全相同&#xff0c;而在二叉树问题分解的一般题目中均会带有返回值&#xff…

el-select 设置宽度 没效果

想实现下面的效果&#xff0c;一行两个&#xff0c;充满el-col12 然后设置了 width100%,当时一直没有效果 解决原因&#xff1a; el-form 添加了 inline 所以删除inline属性 即可

chrome://version/

浏览器输入&#xff1a; chrome://version/ Google浏览器版本号以及安装路径 Google Chrome131.0.6778.205 (正式版本) &#xff08;64 位&#xff09; (cohort: Stable) 修订版本81b36b9535e3e3b610a52df3da48cd81362ec860-refs/branch-heads/6778_155{#8}操作系统Windows…

反向代理块sjbe

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

封装一个sqlite3动态库

作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、项目案例 二…

P1878 舞蹈课(详解)c++

题目链接&#xff1a;P1878 舞蹈课 - 洛谷 | 计算机科学教育新生态 1.题目解析 1&#xff1a;我们可以发现任意两个相邻的都是异性&#xff0c;所以他们的舞蹈技术差值我们都要考虑&#xff0c;4和2的差值是2&#xff0c;2和4的差值是2&#xff0c;4和3的差值是1&#xff0c;根…

【C++学习篇】C++11

目录 ​编辑 1. 初始化列表{} 1.1 C98中的{} 1.2 C11中的{} 2. C11中的std::initializer_list 3. 右值引用和移动语义 3.1 左值和右值 3.2 左值引用和右值引用 3.3 引用延长生命周期 3.4 左值和右值的参数匹配 3.5 右值引⽤和移动语义的使⽤场景 3.5.1 左值引⽤…

Vulnhub靶机随笔-Hackable II

Vulnhub靶机Hackable II详解 攻击机Kali IP:192.168.1.6 靶机 IP:未知 系统:未知 A.信息收集 扫描靶机存活性 确定IP地址 1.命令:arp-scan -l 扫描靶机开放端口及其服务版本信息 2.命令:nmap -A -p- -sV 靶机IP 3.靶机开放三个端口: 21ftp端口:存在anonymous匿…

九.Spring Boot使用 ShardingSphere + MyBatis + Druid 进行分库分表

文章目录 前言一、引入依赖二、创建一个light-db_1备用数据库三、配置文件 application-dev.yml四、创建shardingsphere-config.yml完整项目结构 五、测试总结 前言 在现代化微服务架构中&#xff0c;随着数据量的不断增长&#xff0c;单一数据库已难以满足高可用性、扩展性和…

【第2章:神经网络基础与实现——2.3 多层感知机(MLP)的构建与调优技巧】

在当今科技飞速发展的时代,人工智能早已不是一个陌生的词汇,它已经渗透到我们生活的方方面面,从智能语音助手到自动驾驶汽车,从图像识别到自然语言处理。而支撑这一切的核心技术之一,就是神经网络。作为机器学习领域的璀璨明星,神经网络已经在众多任务中取得了令人瞩目的…

宠物企业宣传网站静态模板 – 前端静态页面开发实例

该宠物宣传企业站是一个基于前端技术构建的静态网站&#xff0c;旨在为宠物行业的企业提供一个简洁、现代的在线展示平台。整个网站采用HTML、CSS和JavaScript三种技术&#xff0c;确保了良好的用户体验和页面表现。 前端技术&#xff1a; HTML&#xff1a;HTML负责构建网站的…

【第4章:循环神经网络(RNN)与长短时记忆网络(LSTM)——4.2 LSTM的引入与解决长期依赖问题的方法】

在人工智能的璀璨星空中,深度学习模型犹如一颗颗耀眼的星辰,引领着技术的革新。而在处理序列数据的领域中,循环神经网络(RNN)无疑是那颗最为亮眼的星星。然而,即便是这样强大的模型,也面临着一些棘手的问题,其中最突出的便是长期依赖问题。今天,我们就来深入探讨一下长…

el-input输入框样式修改

el-input输入框样式修改 目的&#xff1a;蓝色边框去掉、右下角黑色去掉(可能看不清楚) 之前我试过deep不行 最有效的办法就是就是在底部添加一下css文件 代码中针对input的type为textarea&#xff0c;对于非textarea&#xff0c;只需将下面的css样式中的textarea替换成input…

日常问题-pnpm install执行没有node_modules生成

日常问题-pnpm install执行没有node_modules生成 1.问题2.解决方法 1.问题 执行pnpm i后&#xff0c;提示Scope: all 3 workspace projects Done in 503ms&#xff0c;而且没有node_modules生成。很奇怪 2.解决方法 确保根目录有 pnpm-workspace.yaml 文件&#xff1a; 把这…

C++-----------酒店客房管理系统

酒店客房管理系统 要求&#xff1a; 1.客房信息管理:包括客房的编号、类型、价格、状态等信息的录入和修改; 2.顾客信息管理:包括顾客的基本信息、预订信息等的管理; 3.客房预订:客户可以根据需要进行客房的预订&#xff0c;系统会自动判断客房的可用情况; 4.入住管理:客户入住…