听书上说有贪心 + 数据结构的做法,研究了一下。

朴素贪心

考虑把所有线段按照右端点 \(b\) 从小到大排序,依次考虑每一条线段的要求:

  • 如果已经满足要求则跳过
  • 否则尽量选择靠后的数(因为之后的线段的右端点都在这条线段的右边,这样容错更高)

所以,我们可以建一个数组,\(d[i]\) 表示 \(i\) 数字是否选择(填\(1\)或\(0\)),扫一遍 \([l, r]\) 区间求和,然后从后往前贪心放数即可。

对于每条线段需要 \(O(r - l + 1)\)。所以最坏情况下 \(O(n ^ 2)\)。但是轻松 \(52ms\) 过了。

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 50005;
int n, d[N], c[N];
struct Seg{
int a, b, c;
bool operator < (const Seg &x) const {
return b < x.b;
}
}e[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c);
sort(e + 1, e + 1 + n);
int ans = 0;
for (int i = 1; i <= n; i++) {
int l = e[i].a, r = e[i].b, cnt = e[i].c;
for (int j = l; j <= r; j++)
cnt -= d[j];
if(cnt > 0) {
for (int j = r; j >= l && cnt; j--)
if(!d[j]) cnt--, ans++, d[j] = 1;
}
}
printf("%d\n", ans);
return 0;
}

优化

考虑用数据结构优化。

发现我们需要三个操作:

  • 询问 \([l, r]\) 区间的数字个数
  • 将值为 \(x\) 的位置 \(+1\)
  • 从后往前,找到比当前位置靠前的下一个 \(0\) 的位置。
  1. 前两个就是 “区间求和,单调修改”,典型的树状数组。$O(nlog_250000) $

  2. 第三种操作,可以用并查集优化。为什么可以确保时间复杂度呢?对于每一条线段,最多只有一次会枚举到 \(1\) (即开始的那一次),之后每次枚举都会枚举到 \(0\) 的位置,即\(d[i] = 0\),然后把它变成 \(1\),而以后就不会访问到了。而一共有 \(50000\) 个值,所以复杂度是 \(O(50000log_n)\)

\(33ms\)

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 50001;
int n, d[N], c[N], f[N];
struct Seg{
int a, b, c;
bool operator < (const Seg &x) const {
return b < x.b;
}
}e[N];
// 树状数组
int inline ask(int x) {
int res = 0;
for (; x; x -= x & -x) res += c[x];
return res;
} void inline add(int x) {
for (; x < N; x += x & -x) c[x]++;
}
// 并茶集:find(x) 表示找到 <= x 中最大的一个是 0 的数
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
int main() {
scanf("%d", &n);
for (int i = 0; i < N; i++) f[i] = i;
for (int i = 1; i <= n; i++)
scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c);
sort(e + 1, e + 1 + n);
int ans = 0;
for (int i = 1; i <= n; i++) {
int l = e[i].a, r = e[i].b, cnt = e[i].c;
// 取 [l, r] 选了多少个数
cnt -= ask(r) - ask(l - 1);
if(cnt > 0) {
for (int j = r; j >= l && cnt; ) {
// d[j] == 1 的情况每条线段至多出现一次
if(!d[j]) {
cnt--, ans++, d[j] = 1;
// j 被标记成 1 了,要指向 find(j - 1)
f[j] = j - 1;
// 维护树状数组
add(j);
};
if(find(j) != j) j = f[j];
else j--;
}
}
}
printf("%d\n", ans);
return 0;
}

AcWing 362. 区间的更多相关文章

  1. AcWing 803. 区间合并

    网址 https://www.acwing.com/solution/AcWing/content/1590/ 题目描述给定n个区间[l, r]. 合并所有有交集的区间. 输出合并完成后的区间个数. ...

  2. Acwing‘803. 区间合并

    (https://www.acwing.com/problem/content/805/) 给定 nn 个区间 [li,ri][li,ri],要求合并所有有交集的区间. 注意如果在端点处相交,也算有交 ...

  3. AcWing 802. 区间和

    (https://www.acwing.com/problem/content/804/) 假定有一个无限长的数轴,数轴上每个坐标上的数都是0. 现在,我们首先进行 n 次操作,每次操作将某一位置x上 ...

  4. AcWing 802. 区间和 离散化

    https://www.acwing.com/problem/content/804/ #include <iostream> #include <vector> #inclu ...

  5. AcWing 246. 区间最大公约数

    246. 区间最大公约数 思路: 首先根据更相减损术,我们得到一个结论: \(gcd(a_l, a_{l+1}, ...,a_r) = gcd(a_l, a_{l+1}-a_l, a_{l+2}-a_ ...

  6. AcWing 906. 区间分组

    //1.将所有区间按左端点从小到大排序 //2.从前往后处理每个区间,判断能否将其放到某个现有的组中 //判断某一组的最后一个区间的右端点是否小于该区间的左端点 //如果大于或等于,就开新组,如果小于 ...

  7. AcWing 907. 区间覆盖

    //1.将所有区间按照左端点从小到大排序 //2.从前往后依次枚举每个区间 //首先选择能够覆盖左端点的区间当中右端点最靠右的端点 //在所有能覆盖start的区间当中,选择右端点最大的区间 //选完 ...

  8. AcWing 905. 区间选点

    //1.将每个区间按右端点从小到大排序 //2.从前往后依次枚举每个区间,如果当前区间中已经包含点,就直接跳过,否则,选择当前区间的右端点 //选右端点的话,可以尽可能的包含在多个区间里 #inclu ...

  9. AcWing 803. 区间合并

    #include <iostream> #include <vector> #include <algorithm> using namespace std; ty ...

随机推荐

  1. python + appium 执行报错整理

    1.driver.find_element_by_id("com.taobao.taobao:id/searchEdit").send_keys("adidas" ...

  2. thinkphp5.1与layui table表格使用

    第1部分:layui 的 html代码, 即第2部分 thinkphp 控制器方法 index/Dataz/returnShowUser 的view页面 <!DOCTYPE html> & ...

  3. ceph unfound objects 处理

    ceph Vol 45 Issue 1 1.unfound objects blocking cluster, need help! Hi, I have a production cluster o ...

  4. Spring中@Translational注解失效场景

    今天面试被问到@Translational注解什么场景下失效,我一脸懵逼,说的恍恍惚惚的,下来我就总结一下@Translational注解失效的场景! @Transactional 注解相信大家并不陌 ...

  5. 深度分析:SpringBoot异常捕获与封装处理,看完你学会了吗?

    SpringBoot异常处理 简介 ​ 日常开发过程中,难免有的程序会因为某些原因抛出异常,而这些异常一般都是利用try ,catch的方式处理异常或者throw,throws的方式抛出异常不管.这种 ...

  6. 【PYTEST】第三章参数化

    知识点: 参数化 1. parametrize() 参数化测试用例 实际工作中,我们不可能就传一组数据,参数化支持多组数据测试,并且每组都会去执行,parametrize(), 第一个参数用逗号开分隔 ...

  7. zabbix 监控域名证书到期时间!!!!

    在客户端机器上创建脚本 vim /etc/zabbix/zabbix_agentd.d/check-cert-expire.sh #!/bin/sh host=$1port=$2end_date=`o ...

  8. selenium元素定位不到问题分析及解决办法

    最近正在学习写自动化测试脚本,遇到一个错误迟迟未解决,导致自信心大受挫败,甚至想放弃. 思考许久突然想到,我遇到的问题是否也有人会遇到,如果有的话问题就应该有解决办法了.没什么问题是百度解决不了的,如 ...

  9. 浅谈 van Emde Boas 树——从 u 到 log log u 的蜕变

    本文参考算法导论完成. 模板题在此 QwQ 优化的过程比较长,还请读者耐心阅读,认真理解. 最初的想法 我会暴力! 用一个 \(size\) 数组维护每个元素出现的次数. 不细讲,时间复杂度 \(O( ...

  10. 【模版 Luogu P3808/P3796/P5357】AC自动机(简论)

    浙江集训Day9,没有出任何实质性成果,只好把昨天打完的板子记一下. 该博客基于luogu的三道模版题.只有一个大致的讲解,主要提供代码给自己参考. ------------------------- ...