尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

守卫-贪心,线段处理

守卫-贪心,线段处理
📅 发布时间:2026/6/19 9:54:31

P3634 守卫-贪心


P3634 守卫
这个线段处理值的学习

题意

给定区间及权值 \(0/1\),还有总共 \(1\) 的个数 \(k\) ,表示区间内是否有 \(1\) ,问一定为 \(1\) 的点有那些。

思路

很容易发现:

  1. \(0\) 的区间一定没有一。
  2. 去掉 \(0\) 之后长度刚好为 \(k\) 则一定有 \(1\) 。
  3. 值为 1 的区间长度恰好为 \(1\) 的时候,一定满足条件。
  4. 如果存在区间包含关系,保留小的区间。--小的区间外都可以为 \(0\) 。

考虑剩下的区间,容易发现如果在区间相交的地方存在 1 ,可以减少剩余可能存在 1 的区间数量。因为如果权值为 1 的区间内有 1 ,那剩余区间就是可能有 1 ,不符合要求。可以用来判断无解。

考虑 1 最少的情况,因为此时总和最小,如果不选某个点导致总和超过 \(k\) ,则必须选这个点,因为无论如何构造都不会有方式让总和小于 \(k\)。

细节

  1. 1 最少的情况用线段覆盖来求。
  2. 保留的线段权值都为 1 ,且删去权值为 0 的线段。
  3. 判断是否无解要知道在这个点前面作最优解和这个点后面作最优解,所以对得到的最小情况要做一次前缀和和后缀和。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn = 1e5+10;
constexpr int INF = 0x3f3f3f3f3f3f3f3f;typedef struct line
{int l,r;bool operator<(const line &o)const // l为第一关键字{return l!=o.l ? l<o.l : r<o.r;}
}line;int n,k,m;// 长,个数,区间数
int d[maxn];// 差分数组, 标记0的线段覆盖
int idx,cnt;// 线段数量,可能为1的点
line lin[maxn];// 线段-1
int pre[maxn],suf[maxn];// i左边可能为1的点的编号(cnt)
int sti[maxn];// 临时存储剩余的线段下标
int pre_cnt[maxn],suf_cnt[maxn];// 到某个线段最少要选取的点数(前后缀和)
int cov[maxn]; // cnt转坐标signed main()
{#ifndef ONLINE_JUDGEfreopen("cjdl.in","r",stdin);freopen("cjdl.out","w",stdout);#endif // ONLINE_JUDGEscanf("%lld%lld%lld",&n,&k,&m);for(int i=1,a,b,c ;i<=m;++i){scanf("%lld%lld%lld",&a,&b,&c);if(c==0){++d[a];// 差分标记--d[b+1];}else{++idx;lin[idx]={a,b};}}for(int i=1;i<=n;++i){// 还原差分,找剩下1的点d[i+1]+=d[i];if(!d[i]){pre[i]=suf[i]=++cnt;cov[cnt]=i;}}if (k == cnt)// 如果刚好满足,必须要判!{for (int i = 1; i <= cnt; i++){printf("%lld\n", cov[i]);}return 0;}for(int i=1;i<=n;++i)// 映射,似乎可以不用{if(!pre[i]){pre[i]=pre[i-1];}}for(int i=n;i>=1;--i){if(!suf[i]){suf[i]=suf[i+1];}}for(int i=1;i<=idx;++i){lin[i].l=suf[lin[i].l];// 跳过0的点lin[i].r=pre[lin[i].r];}sort(lin+1,lin+1+idx);// 现在排序for(int i=1;i<=idx;++i){if(lin[i].l>lin[i].r){continue;}while(sti[0] && lin[sti[sti[0]]].r>=lin[i].r)// 删除包含小线段的线段{--sti[0];}sti[++sti[0]]=i;}idx=sti[0];for(int i=1;i<=idx;++i){lin[i]=lin[sti[i]];// 挑完的线段}int rr=0;// 前缀最少要选取的点数for(int i=1;i<=idx;++i){if(lin[i].l>rr){pre_cnt[i]=pre_cnt[i-1]+1;rr=lin[i].r;}else{pre_cnt[i]=pre_cnt[i-1];}}int ll=INF;// 后缀for(int i=idx;i>=1;--i){if(lin[i].r<ll){suf_cnt[i]=suf_cnt[i+1]+1;ll=lin[i].l;}else{suf_cnt[i]=suf_cnt[i+1];}}bool flag=0;for(int i=1;i<=idx;++i){if(lin[i].l==lin[i].r)// 一个点必须要{flag=1;printf("%lld\n",cov[lin[i].l]);continue;}if(pre_cnt[i] != pre_cnt[i-1]+1) continue;// 不是有影响的线段右端点int pos=idx+1;int l=i+1,r=idx;// 二分找下一个线段(左端点刚好大) 可以用双指针更快while(l<=r){int mid=l+((r-l)>>1);if(lin[mid].l>lin[i].r-1){pos=mid;r=mid-1;}else{l=mid+1;}}if(pre_cnt[i]+suf_cnt[pos]>k)// 不选这个点无解{flag=1;printf("%lld\n",cov[lin[i].r]);}}if(!flag)// 没有选一个点{printf("-1\n");}return 0;
}

相关新闻

  • 2025年口碑好的不锈钢衣柜优质厂家推荐榜单
  • 2025年质量好的开天品牌口碑榜
  • Python3 OS 文件/目录方法详解

最新新闻

  • 2026淮北黄金回收白银回收铂金回收门店+工商公安双备案+中检认证商家推荐 - 诚金汇钻回收公司
  • Mapbox GL JS 3.25.0 发布:多项功能改进与错误修复,提升性能与稳定性
  • 2026北京本地人必选防水补漏检测维修公司靠谱服务商TOP5推荐:房屋渗漏水检测维修/卫生间/厨房/天花板/阳台/外墙渗漏水检测补漏维修-暗管漏水检测专业仪器精准定位漏水点 - 即刻修防水
  • 网上登报挂失流程是什么?网上登报挂失费用是多少?
  • 深圳南山区金价高企卖金正当时 - 上门黄金回收
  • 常州武进区黄金回收指南:三种硬指标让你卖金不踩坑 - 上门黄金回收

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号