题面

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]守卫的更多相关文章

  1. p3634 [APIO2012]守卫

    传送门 分析 1.先预处理出不被0覆盖的点,然后对每个点处理出在它左边离他最近的点和在他右边理他最近的点. 2.对于每个至少存在一个忍者的区间,先将它左右边界处理为不被0所覆盖.排序后将包含其他区间的 ...

  2. [luogu P1552] [APIO2012]派遣

    [luogu P1552] [APIO2012]派遣 题目背景 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿. 题目描述 在这个帮派里,有一名忍者被称之为Master.除 ...

  3. [NOIP2015]运输计划 线段树or差分二分

    目录 [NOIP2015]运输计划 链接 思路1 暴力数据结构 思路2 二分树上差分 总的 代码1 代码2 [NOIP2015]运输计划 链接 luogu 好久没写博客了,水一篇波. 思路1 暴力数据 ...

  4. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  5. P1083 借教室(差分+二分)

    P1083 借教室 第一眼:线段树. 然鹅懒得写. 正解:差分+二分. 显然订单合法的上线可以二分 然后差分数组维护一下.没了. #include<iostream> #include&l ...

  6. 2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 二分+贪心

    /** 题目:2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 链接:http://codeforces.com/gym/101194 题意:给n个木块,堆 ...

  7. 【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心

    题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...

  8. Codeforces_732D_(二分贪心)

    D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  9. ZZNU-OJ-2098 : Drink coffee【线段树合并区间或者 差分 + 二分索引树】

    : Drink coffee 时间限制: Sec 内存限制: MiB 提交: 答案正确: 提交 状态 讨论区 题目描述 为了在上课时保持清醒,凯伦需要一些咖啡.咖啡爱好者凯伦想知道最佳的温度来冲煮完美 ...

随机推荐

  1. [USACO15JAN]Moovie Mooving G

    [USACO15JAN]Moovie Mooving G 状压难题.不过也好理解. 首先我们根据题意: she does not want to ever visit the same movie t ...

  2. js console.log all in one

    js console.log all in one this & arguments "use strict"; /** * * @author xgqfrms * @li ...

  3. how to make one you own free online tutorials in minutes

    how to make one you own free online tutorials in minutes educative.io https://www.educative.io/colle ...

  4. Java REPL & JShell

    Java REPL & JShell Java 11 JShell Java Shell https://www.infoq.com/articles/jshell-java-repl/ Th ...

  5. input number step

    input number step <!DOCTYPE html> <html> <body> <h1>The input step attribute ...

  6. nasm astrncmp函数 x86

    xxx.asm: %define p1 ebp+8 %define p2 ebp+12 %define p3 ebp+16 section .text global dllmain export as ...

  7. Flutter 真机调试

    先把手机开启开发者模式,并打开USB调试功能(每种机型开启方法可能不一样) flutter devices 查看是否连接 flutter run

  8. NGK算力市场,不止有动静态收益还有SPC空投!

    随着数字货币交易的火热,云算力挖矿也悄然崛起.越来越多的用户开启云算力挖矿,以获取更多的收益.相较于传统的矿机挖矿,用户通过购买算力进行云挖矿,节省了购买矿机以及维护的成本.另一方面,也降低了安全风险 ...

  9. Baccarat凭什么能成为DeFi后时代火爆新趋势?

    在各币种经历涨涨跌跌以后,DeFi后时代已然来临.那么,当前DeFi市场中哪个项目更被市场生态建设者看好呢?毫无疑问,Baccarat会成为最被看好的DeFi项目. Baccarat采用了独特的共识算 ...

  10. 01、初识Java

    目录 前言 一.认识Java 历史介绍 Java介绍 二.认识及安装JDK 1.认识JDK 2.安装JDK 配置与测试 配置注意及不生效解决 3.认识Java虚拟机 三.Java的工作方式 四.jav ...