题面

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. Clipboard API

    Clipboard API click copy click copy demo clickGetNewsLink(data_ref = `newsLink`) { let that = this; ...

  2. 如何给 GitHub 添加 SSH key, 如何生成 SSH key 详细图文教程!

    如何给 GitHub 添加  SSH key, 如何生成  SSH key 详细图文教程! 一. 生成  SSH key https://ide.c9.io/xgqfrms/ 创建一个空项目:(或使用 ...

  3. js console.log color all in one

    js console.log color all in one console.log color Chrome console.log 语法 / grammar %c, %s, css style ...

  4. how to tell a function arguments length in js

    how to tell a function arguments length in js JavaScript函数不对参数值(参数)执行任何检查 https://www.w3schools.com/ ...

  5. Flutter for Desktop

    Flutter for Desktop https://flutter.dev/desktop https://github.com/flutter/flutter/wiki/Desktop-shel ...

  6. Intersection Observer

    Intersection Observer Intersection Observer API https://developer.mozilla.org/en-US/docs/Web/API/Int ...

  7. Dart: List排序

    var list = <Item>[ Item(title: "item 1", isTopping: true), Item(title: "item 2& ...

  8. 看超额担保免信任的NGK DeFi 乐高如何打造下一个千倍币?

    2020年中,DeFi的高收益率吸引了大量热钱涌入,DeFi总锁仓量破百亿美金.如今,流动性挖矿的热潮暂时停歇,但对于 NGK DeFi项目来说,它背后的演变进化从未停止. 免信任是 NGK DeFi ...

  9. ASP.NET Core中如何对不同类型的用户进行区别限流

    老板提出了一个新需求,从某某天起,免费用户每天只能查询100次,收费用户100W次. 这是一个限流问题,聪明的你也一定想到了如何去做:记录用户每一天的查询次数,然后根据当前用户的类型使用不同的数字做比 ...

  10. django学习-12.访问不同url/接口地址实现对指定数据的增删改查功能

    1.前言 通过前面博客[django学习-10.django连接mysql数据库和创建数据表]里的操作,我们已经成功在数据库[hongjingsheng_project]里创建了一张数据表[hello ...