当前位置: 首页 > 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辆湿货中转车)。 货物由不同供货商从各地发来,各地的货物是依次进站,然后小明按照卸货顺序依次装货到中转车,一个供货商的货只能装到一辆车上,不能拆装,但是…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...