Luogu 3634 [APIO 2012] 守卫

2023-05-16

          • 传送门
          • 思路
          • 正解
          • 参考代码

传送门
思路

  感觉自己越来越笨了……首先,很明显这道题需要把没有看到忍者的区间给删去,可以用前缀和 O(n) O ( n ) 处理,然后对没有删去的地方重新标号。重新标号时,需要对发现忍者的区间的左右端点也重新标号,用二分就好了,比较简单(细节留给你们思考)。

  然后我发现,如果一个区间最后只能覆盖一个位置,那么这个区间是必选的。然后我就什么也看不出来了……

正解

  这道题最重要的一点是如何理解某个位置必须存在一个忍者,我们来想一想除了位于一个长度为 1 1 的区间的情况,为什么某个地方必须存在一个忍者。

  由于题目没有限制,我们可以随便放忍者,只要满足所有区间都有至少一个忍者被覆盖到就好了。这很自然地让我们联想到点覆盖线段的问题,自然也就想到了用最少的点覆盖所有线段的问题。

  由于保证至少有一个合法解,那么我们可以知道:覆盖所有线段的最小点数一定小于等于 k,否则问题一定无解。如果有剩下的,那就随便放即可。

  注意到,既然剩下的是随便放,那么它们一定不在最后的答案中。换句话说,最后的答案一定是各区间的右端点,且它在贪心求最小点数时被选中了(如果没有被选,那这个点已经是不能一定选的了)。

  那么我们考虑,为什么一个区间的右端点必须选中。正面考虑显然已经无路可走(选都选了,怎么判断必须选?),我们考虑当不选这个右端点时会发生什么。如果一定不选这个右端点,我们仍然可以在 O(n) O ( n ) 的时间复杂度内求出覆盖所有线段的最小点数,只需要在选这个区间时改成选择右端点左边那个点就可以了,但是这时总点数就可能会变大。我们自然就会想到:如果总点数变得超过 k k ,就说明不选这个点将会产生矛盾,所以这个点必须选

  于是我们立即得到了一个时间复杂度为 O(n2) 的算法。另外,我们发现我们全程都在求最小线段覆盖点数,所以包含了其它线段的线段就没有用了,因为被包含的线段被覆盖就意味着包含的线段也会被覆盖,因此剩下的线段如果按照左端点从小到大排序,它们的右端点也一定是递增的。具体操作用单调栈即可。


  我们考虑优化这个算法。思考这个过程究竟做了什么,我们发现,我们在从左往右决策时前面一定不变,到了规定不能选的右端点后我们一定会选择右端点左边那个点,也就是说,我们知道是知道前面是选了多少个点的。考虑暴力计算时我们后面是怎么算的,我们一定会选择第一个不能被最后一个选的点覆盖的线段的右端点,然后依次覆盖剩下的所有线段我们可以预处理出覆盖后面所有线段的最小点数(从后往前贪心即可),在计算答案时二分查找第一个不能被覆盖的区间,就能在 O(logn) O ( log ⁡ n ) 的时间复杂度内计算不选某个位置时的最小点数了。细节留给你们思考。

参考代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
typedef long long LL;
typedef unsigned long long ULL;
using std::cin;
using std::cout;
using std::endl;
typedef int INT_PUT;
INT_PUT readIn()
{
    INT_PUT a = 0; bool positive = true;
    char ch = getchar();
    while (!(ch == '-' || std::isdigit(ch))) ch = getchar();
    if (ch == '-') { positive = false; ch = getchar(); }
    while (std::isdigit(ch)) { a = a * 10 - (ch - '0'); ch = getchar(); }
    return positive ? -a : a;
}
void printOut(INT_PUT x)
{
    char buffer[20]; int length = 0;
    if (x < 0) putchar('-'); else x = -x;
    do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
    do putchar(buffer[--length]); while (length);
    putchar('\n');
}

const int maxn = int(1e5) + 5;
int n, m, k;
struct Area
{
    int l, r;
    Area() {}
    Area(int l, int r) :l(l), r(r) {}
};
int newIdx[maxn];
std::vector<Area> areas;

int ans[maxn];
void solve1() // n^2
{
    for (int i = 1; i <= n; i++)
    {
        bool bOk = false;
        int pre = -1;
        int cnt = 0;
        for (int j = 0; j < areas.size(); j++)
        {
            if (areas[j].l == i && areas[j].r == i)
            {
                bOk = true;
                break;
            }
            if (areas[j].l <= pre) continue;
            cnt++;
            if (areas[j].r == i)
                pre = areas[j].r - 1;
            else
                pre = areas[j].r;
        }
        if (bOk || cnt > k) ans[++ans[0]] = i;
    }
}
int f[maxn];
int left[maxn];
void solve2()
{
    for (int i = 0; i < areas.size(); i++)
        left[i] = areas[i].l;

    int pre, cnt;
    pre = n + 1;
    cnt = 0;
    for (int i = areas.size() - 1; ~i; i--)
    {
        if (pre > areas[i].r)
        {
            pre = areas[i].l;
            cnt++;
        }
        f[i] = cnt;
    }

    pre = -1;
    cnt = 0;
    for (int i = 0; i < areas.size(); i++)
    {
        const Area& a = areas[i];
        if (pre < a.l) // 只考虑已经选了的点
        {
            if (a.l == a.r)
                ans[++ans[0]] = a.l;
            else
            {
                int R = std::upper_bound(left, left + m, a.r - 1) - left; // 选了 r 左边那个点,即 r - 1
                if (cnt + 1 + f[R] > k)
                    ans[++ans[0]] = a.r;
            }

            pre = a.r;
            cnt++;
        }
    }
}

int del[maxn];
void run()
{
    n = readIn();
    k = readIn();
    m = readIn();
    std::vector<Area> temp;
    for (int i = 1; i <= m; i++)
    {
        int l = readIn();
        int r = readIn();
        int c = readIn();
        if (!c)
        {
            del[l]++;
            del[r + 1]--;
        }
        else
        {
            temp.push_back(Area(l, r));
        }
    }
    for (int i = 2; i <= n; i++)
        del[i] += del[i - 1];
    for (int i = 1; i <= n; i++)
        if (!del[i])
            newIdx[++newIdx[0]] = i;
    for (int i = 0; i < temp.size(); i++)
    {
        Area& a = temp[i];
        a.l = std::lower_bound(newIdx + 1, newIdx + 1 + newIdx[0], a.l) - newIdx;
        a.r = std::upper_bound(newIdx + 1, newIdx + 1 + newIdx[0], a.r) - newIdx - 1;
        if (a.l <= a.r)
            areas.push_back(a);
    }
    temp = areas;
    areas.clear();
    std::sort(temp.begin(), temp.end(),
        [](const Area& a, const Area& b)
    {
        if (a.l != b.l) return a.l < b.l;
        return a.r > b.r;
    });
    for (int i = 0; i < temp.size(); i++)
    {
        const Area& a = temp[i];
        while (areas.size() && areas.back().r >= a.r)
            areas.pop_back();
        areas.push_back(a);
    }

    n = newIdx[0];
    m = areas.size();
    if (k == n) // 特判一下
    {
        for (int i = 1; i <= n; i++)
            printOut(newIdx[i]);
        return;
    }
    solve2();
    if (ans[0])
        for (int i = 1; i <= ans[0]; i++)
            printOut(newIdx[ans[i]]);
    else
        printOut(-1);
}

int main()
{
    run();
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Luogu 3634 [APIO 2012] 守卫 的相关文章

  • SQL Server 2012企业版和标准版的区别

    关于使用Microsoft SQL Server 数据库的公司一般会有疑问 xff0c 企业版数据库和标准版数据库的区别在哪 xff1f 如果采购企业版的价格和标准版的价格相差很大 xff0c 从多方资料查询发现 xff0c 我认为最主要的
  • Windows Server 2012 R2 服务器密码忘记问题

    解决方法 xff1a 1 准备好一张和当前Windows server 2012R2系统版本和位数相近 xff08 最好相同 xff09 的系统镜像光盘或者ISO文件 2 通过BIOS设置系统从光盘启动 出现安装系统的画面 xff0c 点击
  • 再见2011,你好,2012。

    不会写文章 xff0c 这个算是对自己的一个总结吧 xff0c 毕业一年半了 xff0c 从事嵌入式也有一年半了 xff0c 总觉得自己连入门都谈不上 xff0c 整天都看上去很忙 xff0c 有时候确实有一大堆的事情要做 xff0c 但是
  • “激情与梦想 我的程序员之路”—2012高校巡讲

    2012年3月29日下午2点半 xff0c CSDN高校俱乐部项目主管潘永强老师在我校进行了一场以 激情与梦想 xff0c 我的程序员之路 为主题的演讲 信息管理与工程系团总支书记陈春燕 指导老师王洪涛以及杜光辉 刘冲等7位老师出席了该次讲
  • 影响SQL Server数据库应用性能的几个常见因素 (2012/1/18)

    转自 xff1a http blogs msdn com b apgcdsd archive 2012 01 18 sql server 2012 1 18 aspx 影响SQL Server数据库应用性能的几个常见因素 性能问题是困扰数据
  • 题解:luogu P5568 [SDOI2008]校门外的区间

    题解 xff1a luogu P5568 SDOI2008 校门外的区间 luogu P5568 SDOI2008 校门外的区间 前置知识 xff1a 珂朵莉树 问题一 xff1a 开闭区间 区间端点均为整数 xff0c 不妨认为 xff0
  • luogu P1593 因子和

    不要吐槽博主总做这些数论氵题 首先我们看到这种因数问题 果断质因数分解 所以当前数 a 61 p 1 k 1 p 2 k 2 p m k m 可得 a b 61 p 1 k 1 b p 2 k 2 b p m k m b 考虑因数和 假设数
  • 2012服务器系统安装流媒体,windows2012流媒体服务器

    windows2012流媒体服务器 内容精选 换一换 购买Windows弹性云服务器后 xff0c 通过MSTSC远程连接 xff0c 发现没有声音 通过MSTSC远程连接的Windows弹性云服务器如何播放音频 xff1f 本节内容适用于
  • 在Harvester上安装windows sever 2012 r2

    安装Windows Server 2012 r2 文章目录 安装Windows Server 2012 r2新建虚拟机配置基础信息配置卷配置网络开机 xff0c 进入安装系统步骤安装磁盘驱动安装网络驱动安装其他驱动测试网络 Harveste
  • Luogu 3631 [APIO 2011] 方格染色

    传送门思路参考代码细节 传送门 思路 很不错的一道题 xff0c 用到的东西不深 xff0c 但是要想到确实需要一定思维 一开始我想的是动态规划 xff0c 发现如果要设状态需要知道一个格子左边 xff0c 上边和左上边三个格子的状态 然后
  • Luogu 3632 [APIO 2011] 寻路

    传送门正解参考代码 传送门 正解 暴力连边跑最短路就好了 xff0c 只不过代码太长太难写啦 xff01 参考代码 span class hljs preprocessor include lt cstdio gt span span cl
  • Luogu 3647 [APIO 2014] 连珠线

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 又看错题了 题目中说一个新的珠子和一个已经添加的珠子连接起来 xff0c 我没有看到 xff0c 然后就凉了 立个 flag xff1a 已经连续看错五题了 xff0c
  • Luogu 2168 [NOI 2015] 荷马史诗

    传送门思路参考代码 传送门 思路 唉 xff0c 我太弱了 xff0c 什么都不会 xff0c 连哈夫曼树都不会 这道题就是一个 k k 叉哈夫曼树 题目要求满足两个条件 一是代价最小 二是最长长度最小 最长长度最小很好解决 只需要优先合并
  • Luogu 2114 [NOI 2014] 起床困难综合症

    传送门思路参考代码 传送门 思路 按位贪心 但是我太弱了 xff0c 明明可以 O n O n 预处理 xff0c 我却只会 O 32 n O
  • windows Server 2012 R2安装 “vc_redist.x64.exe“ 报错

    问题 xff1a 安装 34 vc redist x64 exe 34 失败 xff0c 0x80240017 未指定的错误 解决 xff1a 安装更新程序 KB2919442 与 KB2919355 KB2919442 下载地址 xff1
  • Nginx windows server 2012部署过程

    部署静态网页到服务器 今天做了一个静态网页 xff0c 想部署带到自己的阿里云服务器 通过查询可以使用tomcat容器或者nginx xff0c 主流方式是nginx部署 xff0c 记录一下自己部署的过程 一 nginx简介 Nginx
  • 我的2011----再见2011!你好2012!

    今天本来是 特别平常的一天 但是因为位置排在了 2011 年的最后 平常也就变得不平常了 一年就在这么转眼即逝中度过了 虽说一年比较短暂 但是回头在看看自己所拥有的这一年 留下的很多 在 2011 我把 ShortBrain 英语进行着 英
  • SQL Server 2012企业版和标准版的区别

    关于使用Microsoft SQL Server 数据库的公司一般会有疑问 xff0c 企业版数据库和标准版数据库的区别在哪 xff1f 如果采购企业版的价格和标准版的价格相差很大 xff0c 从多方资料查询发现 xff0c 我认为最主要的
  • 微软sql服务器如何安装,Microsoft SQL Server 2012 数据库安装图解教程

    1 根据微软的下载提示 xff0c 64位的Windows7操作系统 xff0c 只需下载列表的CHSx64SQLFULL x64 CHS Core box CHSx64SQLFULL x64 CHS Intall exe和CHSx64SQ
  • P1586 四方定理

    Powered by NEFU AB IN Link 文章目录 P1586 四方定理 题意 思路 代码 P1586 四方定理 题意 四方定理是众所周知的 任意一个正整数n 可以分解为不超过四个整数的平方和 给定的正整数n 编程统计它能分解的

随机推荐

  • LaTeX 007:texify 调用 zhmakeindex

    如文档所述 xff0c 在系统增加一个值为 zhmakeindex 路径的环境变量 MAKEINDEX 即可
  • 转载:LaTeX 定义参数变长的命令

    本文作者 xff1a Liam Huang 本文链接 xff1a https liam page 2017 07 30 define a new command with different amount of parameters in
  • 一个简单的 Lex 词法分析程序示例

    作为一个学习 Lex 词法分析程序的例子 xff0c 下面的 lex 程序将会生成一个分析 LaTeX 中命令的词法分析器 下面的程序包含了很多 lex 语言的语法 xff0c 正则表达式除外 正则表达式的用法网上比较多 xff0c 这里不
  • mysql数据库conf配置详解

    mysqld port 61 6033 skip grant tables datadir 61 usr tools mysql data socket 61 usr tools mysql mysql sock user 61 mysql
  • LaTeX 008:比较方便的键入下划线的方式

    在 LaTeX 中 xff0c 我们有时会需要输入下划线 直接键入 是不行的 xff0c 会出现的编译错误 xff0c 正如网友所述 xff0c LaTeX 为了简化对编译错误的处理禁止在文本模式 xff08 text mode xff09
  • LaTeX 009:自定义带有 * 号的命令

    LaTeX 中 xff0c 我们经常见到 section 和 section xff0c 分别表示有编号的 section 和没有编号的 section 我们也想自己定义带有 号的命令 xff0c 但写下面的代码时却报错了 xff1a ne
  • 2022 New Year‘s Resolution

    Some Might Say 2022 New Year 39 s Resolution Some might say we are on the edge of the new era Always are they saying thi
  • C++ 多线程编程导论(中)

    受篇幅限制 xff0c 上半部分不再更新 xff0c 填坑的新内容都放在此文章中 文章目录 参考资料线程安全 xff08 续 xff09 互斥访问 互斥体 xff08 mutex xff09 和锁 xff08 lock xff09 什么是互
  • C++ 使用模板序列化/反序列化固定键值对

    仅是一个原型 xff0c 留作记录 我感觉可以写出非常逆天的代码 span class token macro property span class token directive hash span span class token d
  • 编译原理习题两则(龙书,写出语言的正则定义)

    3 3 5 3 注释 xff0c 即 和 之间的串 xff0c 且串中没有不在双引号 xff08 34 xff09 中的 注 xff1a 假设双引号是匹配的 思路 xff1a 从空串开始写 xff0c 写出整体框架后 xff0c 通过分类讨
  • 2023 New Year‘s Resolution

    This Is Game 2023 New Year 39 s Resolution My 2022 ended with a day of game I am convinced that I am not to blame becaus
  • 补录:2018 和 2019 New Year‘s Resolution

    前言 xff1a 吉光片羽 xff0c 以飨读者 2018 New Year 39 s Resolution One year and a half ago I felt that life in 2020 would be quite d
  • 原博文地址

    由于账号问题 xff0c 现更改为这个账号 xff0c 以下为原博文地址 使用WH MOUSE LL钩子来判断按键是否是mouse event模拟的 http blog csdn net qq 26140973 article detail
  • [NOI 2003] 文本编辑器 Splay 维护序列 / 块状链表

    传送门 xff08 JZOJ xff09 xff08 第一道全国决赛题 xff09 解法 1 xff1a 使用 Splay 维护 不管怎么说 xff0c 总和刚刚学过的迎合上了 这道题可以直接上 Splay 维护线性序列 xff0c 光标位
  • 一次macOS的升级填坑(macOS Catalina - macOS Monterey)

    目录 小序一 升级前操作二 升级中三 问题填坑1 像我一样长时间卡在一个进度条怎么办2 在更新途中重启过电脑 xff08 完整流程填坑 xff09 3 安装之后不能开机 xff0c 如何紧急拷贝资料4 安装不成功 xff0c 如何重新安装系
  • CF 713C Sonya and Problem Wihtout a Legend

    文章目录 传送门题目大意正解通过维护关键点来维护信息参考代码 传送门 题目大意 给定一个长度为 n n 3000
  • Luogu 3642 [APIO 2016] 烟火表演

    传送门引例 xff08 上一道题 xff09 凸函数一开始的思路正解参考代码总结 传送门 引例 xff08 上一道题 xff09 凸函数 回忆我们上一道题是怎么做的 我们维护的东西的实质是一个 xff08 下 xff09 凸函数 由于我们的
  • Luogu 3631 [APIO 2011] 方格染色

    传送门思路参考代码细节 传送门 思路 很不错的一道题 xff0c 用到的东西不深 xff0c 但是要想到确实需要一定思维 一开始我想的是动态规划 xff0c 发现如果要设状态需要知道一个格子左边 xff0c 上边和左上边三个格子的状态 然后
  • Luogu 3632 [APIO 2011] 寻路

    传送门正解参考代码 传送门 正解 暴力连边跑最短路就好了 xff0c 只不过代码太长太难写啦 xff01 参考代码 span class hljs preprocessor include lt cstdio gt span span cl
  • Luogu 3634 [APIO 2012] 守卫

    传送门思路正解参考代码 传送门 思路 感觉自己越来越笨了 首先 xff0c 很明显这道题需要把没有看到忍者的区间给删去 xff0c 可以用前缀和 O n O n 处理 xff0c 然后对没有删去的地方重新标号 重新标号时 xff0c 需要对