当前位置: 首页 > news >正文

XCPC第十三站,贪心问题

在这里插入图片描述

一.区间选点

在这里插入图片描述
        我们采取这样的策略来选点:step(1)将区间按照右端点的大小从小到大排序;step(2)从前往后依次枚举每个区间,如果当前区间中已经包含点,直接pass,否则选当前区间的右端点。因为右端点是最容易被下一个区间包含进去的,所以我们每次选择的都是当前情况下的局部最优解,这种策略就叫作贪心。
        设最优解的点数是ans,按照算法找到的点数是cnt,下面我们证明ans == cnt。首先证明ans<=cnt。根据算法思路,这样选择以后每个区间都包含了点(否则会选右端点),因此算法得到一个可行解。又ans是所有可行解的最小值,因此ans<=cnt。再证明ans>=cnt。如果要执行选一个新的点的操作,那么后一个区间和前一个区间一定无交集。这样一来,我们就至少得到了cnt个互不相交的区间,每个这样的区间我们都选了它的右端点。要覆盖这些区间至少需要cnt个点,因此ans>=cnt。终上,ans == cnt。

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int res;
struct range
{int l,r;bool operator< (const range W)const{return r<W.r;}
}range[N];
int main()
{int n;cin>>n;//要从0开始读入而不能从1开始读入,因为排序的是编号从0到(n-1)的数据,如果读到n的话会导致最后一个数据没有排序。//从小到大枚举每个区间for(int i = 0;i<n;i++){int a,b;cin>>a>>b;range[i] = {a,b};}sort(range,range+n);//ed表示枚举的上一个区间的右端点。初始时赋值为负无穷,这是因为第一次总是要加点的。int ed = -2e9;//要从0开始不能从1开始,理由同上for(int i = 0;i<n;i++){//上一个区间的右端点小于当前区间的左端点,说明两个区间没有交集,那么就要选一个新的点if(ed<range[i].l){res++;//更新右端点的值ed = range[i].r;}}cout<<res<<endl;
}

二.最大不相交区间数量

在这里插入图片描述

        本题代码与上一题完全相同。下面我们来说明为什么按照上题策略选出的点数即为最大不相交区间数量。设ans为最大不相交区间数量,cnt为按照算法找出的区间数量。根据上题,根据算法选出的区间没有交集,因此是一个可行解。而ans是可行解的最大值,因此ans>=cnt。再证明ans<=cnt。采用反证法。假设ans>cnt,说明我们可以找到ans个互不相交的区间,要用点把这些区间覆盖至少需要ans>cnt个点。但是根据第一题,cnt个点已经可以把所有选出的区间覆盖,矛盾。终上,ans ==cnt。

三.区间分组

在这里插入图片描述
        对于本题,我们的策略如下:step(1)将所有区间按照左端点从小到大排序;step(2)从前往后枚举所有区间,枚举当前已有的所有组,判断能否将该区间放进已有的某个组中(即判断某个是否有某个组的区间的右端点最大值小于当前区间的左端点,若<,可以放机;否则无法放进)。若可以放进某个组,就放进去并更新该组右端点的最大值;若不存在这样的组,就开一个新组把这个区间放进去。

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 100010;
struct range
{int l,r;//重载小于号bool operator<(const range W) const{return l<W.l;}
}range[N];
int main()
{int n;cin>>n;for(int i = 0;i<n;i++){int a,b;cin>>a>>b;range[i] = {a,b};}//将区间按照左端点从小到大排序sort(range,range+n);//堆里存储的是各个组的最大右端点priority_queue<int,vector<int>,greater<int> >heap;//从前往后扫描区间for(int i = 0;i<n;i++){//如果堆是空的或者堆的最小值(即所有最大右端点的最小值)仍然大于等于当前区间的左端点,说明不存在某个组,其内的区间与当前区间均无交集,这时候就要开一个新的组。if(heap.empty()||heap.top()>=range[i].l)    heap.push(range[i].r);//否则这样的区间存在,放进这个组即可。为了平衡组数,要把堆顶弹出(否则算heap元素个数的时候会多算一个),并且让当前区间的右端点入堆,参与最小最右端点的“选拔”else if(heap.top()<range[i].l){//此时可以放进某个组,为了更新最右端点的最小值我们要把rangeheap.pop();heap.push(range[i].r);}}cout<<heap.size()<<endl;return 0;
}

        下面我们证明根据这种策略得到的组数就是答案。记正确答案为ans,根据算法选出的答案是cnt,那么由于算法可以选出一种可行方案,ans<=cnt。而怎么证明ans>=cnt呢?我们考察最后一次开新组的时刻。
在这里插入图片描述
        在该时刻,前cnt-1组的max_r都要比当前区间的l大(也就是要开新组的情形)。但是由于我们是按照左端点从小到大排序的,而该区间在最后才被放进去,因此它的l要大于前面所有max_r的区间的l,故它的l就是前面这些max_r属于的区间的一个交点。加上该区间本身,一共有cnt个区间,它们存在交集,因此必须把它们分开,因此ans>=cnt。终上,ans == cnt。

四.区间覆盖

        我们采取这样的策略:step(1)将所有区间按照左端点从小到大排序;step(2)从前往后枚举每个区间,每次选择有可能覆盖左端点(start)的区间中右端点最靠右的区间(贪心的),再讲start更新成右端点的最大值。为什么按照这种策略得到的区间数目就是要求的答案呢?假设最佳方案选出的区间数是ans,算法选出的区间数是cnt。我们选择答案的区间组和算法的区间组的第一个不同的区间(假设是第二个),那么由于算法选择的是可能覆盖左端点的右端点最靠右的区间,因此有r1<=r2.又要不留缝隙,所以l1<=r1。所以l1<=r1<=r2。因此我们可以把上面的区间换成下面的区间。对其它不同的区间做类似操作,便可知道cnt == ans。
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int s,t,n,res;
struct range
{int l,r;//重载小于号bool operator < (const range W)const{return l<W.l;}
}range[N];
int main()
{cin>>s>>t>>n;for(int i = 0;i<n;i++){int a,b;cin>>a>>b;range[i].l = a;range[i].r = b;}//将区间按照左端点从小到大排序sort(range,range+n);bool flag = false;//双指针算法,依次处理每个区间for (int i = 0; i < n; i ++ ){//选择可能覆盖左端点的区间中右端点最靠右的区间int j = i, r = -2e9;while (j < n && range[j].l <= s){r = max(r, range[j].r);j ++ ;}
//如果所有可能覆盖左端点的区间中右端点最靠右的区间的右端点都够不到给定区间的左端点,说明无法覆盖if (r < s){res = -1;break;}
//否则能成功覆盖,所需的区间数加一res ++ ;//如果r>=t说明给定的区间已经被完全覆盖,不再需要执行循环,退出即可if (r >= t){flag = true;break;}
//更新s和i的值,进行下一轮s = r;i = j - 1; }if (!flag) res = -1;printf("%d\n", res);return 0;
}

五.排队打水

在这里插入图片描述        假设第i个打水的人用时为ti,那么总的等待时间就应该是t1*(n-1)+t2*(n-2)+……+tn-1这里我们直接给出一种贪心的策略:按照用时的多少从小到大排队。下面我们证明这种方法的等待时间是最少的。下面假设t1<t2<……tn。假若最优解不是按照时间长短来依次打水,那么一定存在相邻的两个人(记为j和tj+1)满足tj>tj+1。现在我们将这两个人打水的顺序调换,不影响其他人的等待时间,但是我们减少了tj*(n-j)+tj+1*(n-j-1)-tj+1*(n-j)-tj*(n-j-1) = (tj - tj+1)>0,时间减少,这与当前解已是最优解矛盾!

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
//结果可能很大
long long res;
int t[N];int main()
{int n;cin>>n;//因为排序从t这个指针开始,所以我们读入时要从下标0开始读入for(int i = 0;i<n;i++) cin>>t[i];sort(t,t+n);//因为下标从0开始了,所以乘的数要相应地变成(n-i-1)for(int i = 0;i<n;i++)  res+=(n-i-1)*t[i];cout<<res;return 0;
}

六.货仓选址

在这里插入图片描述
        我们首先将坐标按照从小到大的顺序排好。假设选址的位置为x,商店的位置分别为x1,x2,x3,……,xn。那么距离之和f(x)= |x-x1|+|x-x2|+……+|x-xn|。我们将它们两两合成一组,那么就是f(x) = |x-x1|+|x-xn|+|x-x2|+|x-xn-1|+……。根据绝对值不等式,f(x)>=|xn-x1|+|xn-1 - x2|+……而等号恰好可以同时取得(即x在中位数的地方)。如图——
在这里插入图片描述

#include <algorithm>
#include<iostream>
using namespace std;const int N = 100005;int n, res;
int a[N];int main()
{cin>>n;for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);sort(a, a + n);for (int i = 0; i < n; i ++ ) res += abs(a[i] - a[n >> 1]);printf("%d\n", res);return 0;
}

七.耍杂技的牛

在这里插入图片描述
        下面风格给出一种贪心策略:

#include<iostream>
#include<limits.h>
#include<algorithm>
using namespace std;
const int K = 50010;
int sum;
int res = INT_MIN;
typedef pair<int,int> PII;
PII cows[K];
int main()
{int N;cin>>N;for(int i = 0;i<N;i++){int w,s;cin>>w>>s;cows[i] = {w+s,w};}sort(cows,cows+N);for(int i = 0;i<N;i++){int w = cows[i].second,s = cows[i].first - w;res = max(res,sum - s);sum+=w;}cout<<res;return 0;
}

相关文章:

XCPC第十三站,贪心问题

一.区间选点 我们采取这样的策略来选点&#xff1a;step&#xff08;1&#xff09;将区间按照右端点的大小从小到大排序&#xff1b;step&#xff08;2&#xff09;从前往后依次枚举每个区间&#xff0c;如果当前区间中已经包含点&#xff0c;直接pass&#xff0c;否则选当前区…...

一文让你吃透 Vue3中的组件间通讯 【一篇通】

文章目录前情回顾前言1. 父组件 > 子组件通讯传递2. 子组件 > 父组件通讯传递3. 爷孙组件&#xff0c;后代组件通讯数据总结前情回顾 在本专栏前一章节中&#xff0c;我为大家带来了 Vue3 新特性变化上手指南 的归纳梳理&#xff0c;主要介绍了 Vue3 的 Proxy 响应式原理…...

EVE遭遇大规模DDOS攻击,玩家和官方都傻眼了

如果你恰好是一名《星战前夜》&#xff08;EVE&#xff09;的国际服玩家&#xff08;虽然这个几率很小&#xff09;&#xff0c;又恰好因为疫情一直待在家里&#xff0c;那你就真是倒霉透顶了。因为从1月底开始&#xff0c;EVE的服务器就一直受到大规模的DDOS攻击&#xff0c;而…...

【数据结构】二叉树及相关习题详解

新年新气象! 祝大家兔年 财源滚滚! 万事胜意! 文章目录前言1. 树的一些基础概念1.1 树的一些基本概念1.2 树的一些重要概念2. 二叉树的一些基本概念2.1 二叉树的结构2.2 两种特殊的二叉树3. 二叉树的性质4. 二叉树的存储5. 二叉树的基本操作5.1 构造一棵二叉树5.2 二叉树的遍历…...

锂电池充电的同时也能放电吗?

大家应该都有这样经历&#xff0c;我们的手机在充电的同时也能边使用&#xff0c;有的同学就会说了&#xff0c;这是因为手机电池在充电的同时也在放电。如果这样想我们可能就把锂电池类比了一个蓄水池&#xff0c;以为它在进水的同时也能出水&#xff0c;其实这个比喻是错误的…...

通信工程考研英语复试专有名词翻译

中文英文频分多址Frequency Division Multiple Access码分多址Code Division Multiple Access时分多址Time Division Multiple Access移动通信mobile communication人工智能artificial intelligence水声通信Middle-Range Uwa Communication正交频分复用Orthogonal frequency di…...

注意力机制(四):多头注意力

专栏&#xff1a;神经网络复现目录 注意力机制 注意力机制&#xff08;Attention Mechanism&#xff09;是一种人工智能技术&#xff0c;它可以让神经网络在处理序列数据时&#xff0c;专注于关键信息的部分&#xff0c;同时忽略不重要的部分。在自然语言处理、计算机视觉、语…...

【2023Unity游戏开发教程】零基础带你从小白到超神19——射线检测

文章目录 射线检测从某点发射一条射线从摄像机发射一条射线射线检测 游戏中的红外线,默认肉眼是看不到的,从某个初始点开始,沿着特定的方向发射一条不可见且无限长的射线,通过此射线检测是否有任何模型添加了Collider碰撞器组件。一旦检测到碰撞,停止射线继续发射。 碰撞检…...

内存泄漏和内存溢出的区别

参考答案 内存溢出(out of memory)&#xff1a;指程序在申请内存时&#xff0c;没有足够的内存空间供其使用&#xff0c;出现 out of memory。内存泄露(memory leak)&#xff1a;指程序在申请内存后&#xff0c;无法释放已申请的内存空间&#xff0c;内存泄露堆积会导致内存被…...

文本三剑客之sed编辑器

文本三剑客&#xff1a;都是按行读取后处理。 grep 过滤行内容。awk 过滤字段。sed 过滤行内容&#xff1b;修改行内容。sed编辑器 sed是一种流编辑器&#xff0c;流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。 sed编辑器可以根据命令来处理数据流中…...

深度学习:GPT1、GPT2、GPT-3

深度学习&#xff1a;GPT1、GPT2、GPT3的原理与模型代码解读GPT-1IntroductionFramework自监督学习微调ExperimentGPT-2IntroductionApproachConclusionGPT-3GPT-1 Introduction GPT-1&#xff08;Generative Pre-training Transformer-1&#xff09;是由OpenAI于2018年发布的…...

使用Docker 一键部署SpringBoot和SpringCloud项目

使用Docker 一键部署SpringBoot和SpringCloud项目 1. 准备工作2. 创建Dockerfile3. 创建Docker Compose文件4. 构建和运行Docker镜像5. 验证部署6. 总结Docker是一个非常流行的容器化技术,可以方便地将应用程序和服务打包成容器并运行在不同的环境中。在本篇博客中,我将向您展…...

【数据结构】用栈实现队列

&#x1f4af;&#x1f4af;&#x1f4af; 本篇总结利用栈如何实现队列的相关操作&#xff0c;不难观察&#xff0c;栈和队列是可以相互转化的&#xff0c;需要好好总结它们的特性&#xff0c;构造出一个恰当的结构来实现即可&#xff0c;所以本篇难点不在代码思维&#xff0c;…...

[Netty源码] 服务端启动过程 (二)

文章目录1.ServerBootstrap2.服务端启动过程3.具体步骤分析3.1 创建服务端Channel3.2 初始化服务端Channel3.3 注册selector3.4 端口绑定1.ServerBootstrap ServerBootstrap引导服务端启动流程: //主EventLoopGroup NioEventLoopGroup master new NioEventLoopGroup(); //从E…...

Week 14

代码源每日一题Div2 106. 订单编号 原题链接&#xff1a;订单编号 思路&#xff1a;这题本来没啥思路&#xff0c;直到获得了某位佬的提示才会做&#xff08; 我们可以用set来维护一些区间&#xff0c;这些区间为 pair 类型&#xff0c;表示没有使用过的编号&#xff0c;每次…...

【微信小程序】-- 使用 Git 管理项目(五十)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…...

leetcode每日一题:134. 加油站

系列&#xff1a;贪心算法 语言&#xff1a;java 题目来源&#xff1a;Leetcode134. 加油站 题目 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[…...

开放式基金实时排行 API 数据接口

开放式基金实时排行 API 数据接口 多维度参数返回&#xff0c;实时数据&#xff0c;类型参数筛选。 1. 产品功能 返回实时开放式基金排行数据可定义查询基金类型参数&#xff1b;多个基金属性值返回多维指标&#xff0c;一次查询毫秒级返回&#xff1b;数据持续更新与维护&am…...

Android开发中synchronized的实现原理

synchronized的三种使用方式 **1.修饰实例方法,**作用于当前实例加锁&#xff0c;进入同步代码前要获得当前实例的锁。 没有问题的写法&#xff1a; public class AccountingSync implements Runnable{//共享资源(临界资源)static int i0;/*** synchronized 修饰实例方法*/p…...

【华为OD机试 2023最新 】 统一限载货物数最小值(C++)

题目描述 火车站附近的货物中转站负责将到站货物运往仓库,小明在中转站负责调度2K辆中转车(K辆干货中转车,K辆湿货中转车)。 货物由不同供货商从各地发来,各地的货物是依次进站,然后小明按照卸货顺序依次装货到中转车,一个供货商的货只能装到一辆车上,不能拆装,但是…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...