[差分][二分][贪心]luogu P3634 [APIO2012]守卫
题面
https://www.luogu.com.cn/problem/P3634
给m个限制,可以是一段区间中必须有或者必须无忍者
最多有k个忍者,问有多少个位点一定有忍者
分析
首先用差分标记一下0忍者的区间,去掉
然后再删去包含了其他区间的区间,没有意义
将剩余区间按左端点排序,方便处理
考虑计算处理到第i个区间所需的最少忍者数,如果该区间内没有已经被选择的点,贪心选择右端点使总点数最少
倒着处理一遍,类似,不过是贪心选择左端点
枚举每个右端点考虑不选择它而选择它的左侧端点,并二分找到不与它相交的最近的左右两个区间
若从左侧开始处理到左侧区间的最少忍者数+从右侧开始处理到右侧区间的最少忍者数+1(选择当前区间)的所需忍者数大于k,那么说明不选这个右端点是不合法的,所以这个点必选
代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1e5+10;
struct Guard {
int a,b,c;
}g[N];
int n,k,m,zm,gcnt;
int zer[N],ref[N],rcnt,nearl[N],nearr[N],f[N],h[N];
bool ans; bool CMP(Guard a,Guard b) {return a.a<b.a;} int main() {
scanf("%d%d%d",&n,&k,&m);
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&g[i].a,&g[i].b,&g[i].c);
if (!g[i].c) zer[g[i].a]++,zer[g[i].b+1]--;
}
for (int i=1;i<=n;i++) {
zer[i]+=zer[i-1];
if (!zer[i]) ref[nearl[i]=nearr[i]=++rcnt]=i;
else nearl[i]=n+1;
}
if (rcnt==k) {for (int i=1;i<=rcnt;i++) printf("%d\n",ref[i]);return 0;}
for (int i=2;i<=n;i++) nearr[i]=max(nearr[i],nearr[i-1]),nearl[n-i+1]=min(nearl[n-i+1],nearl[n-i+2]);
for (int i=1;i<=m;i++) if (g[i].c&&nearl[g[i].a]<=nearr[g[i].b]) g[++zm].a=nearl[g[i].a],g[zm].b=nearr[g[i].b];
sort(g+1,g+zm+1,CMP);
for (int i=1;i<=zm;i++) {
while (gcnt&&g[gcnt].a<=g[i].a&&g[i].b<=g[gcnt].b) gcnt--;
g[++gcnt]=g[i];
}
for (int i=1,r=0;i<=gcnt;i++) if (g[i].a>r) f[i]=f[i-1]+1,r=g[i].b; else f[i]=f[i-1];
for (int i=gcnt,l=n+1;i;i--) if (g[i].b<l) h[i]=h[i+1]+1,l=g[i].a; else h[i]=h[i+1];
for (int i=1,l,r,mid,ansl,ansr;i<=gcnt;i++)
if (f[i]!=f[i-1])
if (g[i].a==g[i].b) printf("%d\n",ref[g[i].b]),ans=1;
else {
l=1;r=i-1;ansl=0;
while (l<=r) {
mid=l+r>>1;
if (g[mid].b<g[i].b-1) l=mid+1,ansl=mid; else r=mid-1;
}
l=i+1;r=gcnt;ansr=n+1;
while (l<=r) {
mid=l+r>>1;
if (g[mid].a>g[i].b-1) r=mid-1,ansr=mid; else l=mid+1;
}
if (f[ansl]+1+h[ansr]>k) printf("%d\n",ref[g[i].b]),ans=1;
}
if (!ans) printf("-1\n");
}
[差分][二分][贪心]luogu P3634 [APIO2012]守卫的更多相关文章
- p3634 [APIO2012]守卫
传送门 分析 1.先预处理出不被0覆盖的点,然后对每个点处理出在它左边离他最近的点和在他右边理他最近的点. 2.对于每个至少存在一个忍者的区间,先将它左右边界处理为不被0所覆盖.排序后将包含其他区间的 ...
- [luogu P1552] [APIO2012]派遣
[luogu P1552] [APIO2012]派遣 题目背景 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿. 题目描述 在这个帮派里,有一名忍者被称之为Master.除 ...
- [NOIP2015]运输计划 线段树or差分二分
目录 [NOIP2015]运输计划 链接 思路1 暴力数据结构 思路2 二分树上差分 总的 代码1 代码2 [NOIP2015]运输计划 链接 luogu 好久没写博客了,水一篇波. 思路1 暴力数据 ...
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
- P1083 借教室(差分+二分)
P1083 借教室 第一眼:线段树. 然鹅懒得写. 正解:差分+二分. 显然订单合法的上线可以二分 然后差分数组维护一下.没了. #include<iostream> #include&l ...
- 2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 二分+贪心
/** 题目:2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 链接:http://codeforces.com/gym/101194 题意:给n个木块,堆 ...
- 【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心
题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...
- Codeforces_732D_(二分贪心)
D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...
- ZZNU-OJ-2098 : Drink coffee【线段树合并区间或者 差分 + 二分索引树】
: Drink coffee 时间限制: Sec 内存限制: MiB 提交: 答案正确: 提交 状态 讨论区 题目描述 为了在上课时保持清醒,凯伦需要一些咖啡.咖啡爱好者凯伦想知道最佳的温度来冲煮完美 ...
随机推荐
- tree traversal
tree traversal tree 遍历 中序,顺序,左中右 先序,先父节点,中左右 后序,先子节点,左右中 二叉搜索树 "use strict"; /** * * @auth ...
- VS Code & terminal & Canvas & DOM
VS Code & terminal & Canvas & DOM https://code.visualstudio.com/docs/editor/integrated-t ...
- taro ENV & NODE_ENV & process.env
taro ENV & NODE_ENV & process.env https://github.com/NervJS/taro-ui/blob/dev/src/common/util ...
- Rollup & Webpack & Parcel
Rollup & Webpack & Parcel package bundler https://x-team.com/blog/rollup-webpack-parcel-comp ...
- modal 遮罩层,滚动穿透 bug
modal 遮罩层,滚动 穿透bug float 弹层 taro 小程序弹框 滚动击穿 问题 https://segmentfault.com/q/1010000011134345 solution ...
- 小程序 in action
小程序 in action https://github.com/xgqfrms/xcx-taro taro https://taro-docs.jd.com/taro/docs/README.htm ...
- js 上传图片,用户自定义截取图片大小
js 上传图片,用户自定义截取图片大小 js 组件
- InnoDB -- 行记录格式
本文转载自InnoDB -- 行记录格式 分类 Named File Format InnoDB早期的文件格式(页格式)为Antelope,可以定义两种行记录格式,分别是Compact和Redunda ...
- [Python学习笔记]文件的读取写入
文件与文件路径 路径合成 os.path.join() 在Windows上,路径中以倒斜杠作为文件夹之间的分隔符,Linux或OS X中则是正斜杠.如果想要程序正确运行于所有操作系统上,就必须要处理这 ...
- alpakka-kafka(2)-consumer
alpakka-kafka-consumer的功能描述很简单:向kafka订阅某些topic然后把读到的消息传给akka-streams做业务处理.在kafka-consumer的实现细节上,为了达到 ...