【算法小白周赛1D】K阶恒星系 - 题解和代码

devtools/2024/9/23 19:39:59/

题目链接:https://www.starrycoding.com/contest/3/D

题目描述

牛马座 A 是个巨大的椭圆星系,具有 n n n 个恒星。和太阳系一样,每个恒星周围都有许多行星。侥幸团队通过太空望远镜,观测出每个恒星系里行星的数量,其中第 i i i 个恒星系里有 p i p_i pi个行星。若第 i i i 个恒星系为侥幸团队定义的 k k k阶恒星系,则在正整数序列 $(p_1,p_2,… p_n)
中, 中, 中,p_i$ 的左边和右边都至少有 k k k 个元素的值小于 p i p_i pi

现在,侥幸团队请你统计出牛马座 A 中 k k k 阶恒星系的数量。

输入格式

输入数据有 2 2 2 行,第一行输入 2 2 2 个正整数 n , k n,k n,k,分别表示恒星的数量和满足定义的 k k k 值。

第二行:由 n n n 个正整数构成的序列 p 1 , p 2 , . . . , p n p_1,p_2,..., p_n p1,p2,...,pn

输出格式

一行一个正整数,表示牛马座 A 中 k k k阶恒星系的数量。

样例

样例输入#1
10 2
8 8 10 7 4 8 2 1 7 4
样例输出#1
2

解释#1

加粗的数字代表 k k k阶恒星系:8 8 10 7 4 8 2 1 7 4

样例输入#2
20 3
15 8 15 5 9 8 11 12 7 4 3 11 15 6 20 11 2 11 1 13
样例输出#2
5

数据范围

对于所有数据:

  • 1000 ≤ n ≤ 1 0 6 1000 ≤ n ≤ 10^6 1000n106
  • 50 ≤ k ≤ 1 0 5 50 ≤ k ≤ 10^5 50k105
  • 1 ≤ p i ≤ n 1 ≤ p_i ≤ n 1pin

题解

题目大意:

有多少个数字前后都有 m m m个数字比这个数字小。

做法一:优先队列

我们先讨论 p i p_i pi 左侧的情况,右侧按照同样的逻辑做处理就可以了:

注意到,我们只关心有没有至少 k 个元素,而不关心是哪些元素小于 p i p_i pi。因此,我们可以贪心地维护到当前位置时,最小的 k k k 个元素。如果这 k k k 个元素中最大的数字小于 p i p_i pi,则说明可以选出 k k k个来。否则不满足,并且 p i p_i pi 可以替换掉原来的 k k k个元素中的最大数。

从上面可以看出,我们要动态地维护 k k k 个元素,并且要频繁查询、删除最大值,和插入一个元素,用优先队列(大根堆)即可。

然后右侧同理。

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

AC Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
int n, k, p[N], ans;
bool f[N], g[N];
priority_queue<int> qf, qg;  // 维护到当前位置前最小的 k 个元素
int main(){ios::sync_with_stdio(0);cin.tie(0);cin >> n >> k;for(int i = 1; i <= n; i++) {cin >> p[i];if(qf.size() < k) qf.push(p[i]), f[i] = false;else if(p[i] > qf.top()) f[i] = true;else qf.pop(), qf.push(p[i]), f[i] = false;}for(int i = n; i >= 1; i--) {if(qg.size() < k) qg.push(p[i]), g[i] = false;else if(p[i] > qg.top()) g[i] = true;else qg.pop(), qg.push(p[i]), g[i] = false;}for(int i = 1; i <= n; i++) {if(f[i] && g[i]) ans++;}cout << ans;return 0;
}

做法二:树状数组

观察到我们只需要找 p i p_i pi前后有多少个数字比自己大,很像一个求解逆序对问题,所以可以直接用树状数组

我们可以把所有的数字全部插入,设最大数为 m a x n maxn maxn,我们依次判断 a i a_i ai前面即 q u e r y ( a i − 1 ) query(a_i-1) query(ai1)以及 a i a_i ai后面即 q u e r y ( m a x n ) − q u e r y ( a i ) query(maxn)-query(a_i) query(maxn)query(ai)是否含有 k k k个数字,插入比较简单,单点插入权值为1的数字即可。

AC Code

#pragma GCC optimize(3,"Ofast","inline")
#pragma GCC target ("avx")
#pragma GCC optimize ("inline")#include <bits/stdc++.h>#define ios_close std::ios::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr)using i64 = long long;
using u64 = unsigned long long;
using ld = long double;
#define Pi  acos(-1.0)template<typename T>
class BIT{
public:int sz;std::vector<T> t;BIT(){}BIT(int n){sz = n;t = std::vector<T>(sz + 1);}int lowbit(int x){return x & (-x);}void modfity(int x, T val){for(int i = x; i <= sz; i += lowbit(i)){t[i] += val;}       }T query(int x){T ans = 0;for(int i = x; i >= 1; i -= lowbit(i)){ans += t[i];}return ans;}
};void solve(){int n, k;std::cin >> n >> k;BIT<int> pre(n);std::vector<int> a(n + 1);std::vector<int> l(n + 1);std::vector<int> r(n + 1);for(int i = 1; i <= n; i ++ ){std::cin >> a[i];l[i] = pre.query(a[i] - 1);pre.modfity(a[i], 1);}BIT<int> suf(n);for(int i = n; i >= 1; i -- ){r[i] = suf.query(a[i] - 1);suf.modfity(a[i], 1);}int ans = 0;for(int i = 1; i <= n; i ++ ){//std::cout << l[i] << " " << r[i] << '\n';if(l[i] >= k && r[i] >= k){//std::cout << i << '\n';ans ++;}}std::cout << ans;
}int main(){
#if 0ios_close;
#endif#if 1freopen("kgalaxy.in", "r", stdin);freopen("kgalaxy.out", "w", stdout);
#endifint T = 1;
#if 0std::cin >> T;
#endif#if 0scanf("%d", &T);
#endifwhile(T -- ){solve();}return 0;
}

StarryCoding - 编程开发新手村,非常适合新手小白的一个网站,推荐给大家~

5月1日晚上还有一场入门教育赛,欢迎来玩:https://www.starrycoding.com/contest/5


http://www.ppmy.cn/devtools/26942.html

相关文章

2024五一数学建模竞赛(五一赛)选题建议+初步分析

提示&#xff1a;DS C君认为的难度&#xff1a;B>A>C&#xff0c;开放度&#xff1a;AB<C。 以下为A-C题选题建议及初步分析&#xff1a; A题&#xff1a;钢板最优切割路径问题 l 难度评估&#xff1a;中等难度。涉及数学建模和优化算法&#xff0c;需要设计最优的…

深入浅出DBus-C++:Linux下的高效IPC通信

目录标题 1. DBus简介2. DBus-C的优势3. 安装DBus-C4. 使用DBus-C初始化和连接到DBus定义接口和方法发送和接收信号 5. dbus-cpp 0.9.0 的安装6. 创建一个 DBus 服务7. 客户端的实现8. 编译和运行你的应用9. 瑞芯微&#xff08;Rockchip&#xff09;的 Linux 系统通常会自带 db…

使用SDRPI运行openwifi和设置网口

目录 一 制作启动盘 二 使用串口的方式启动openwifi 三 无线连接 四 网口设置&#xff0c;有线连接 五 使用SSH登录 一 制作启动盘 在github上下载img文件&#xff0c;由于github上下载速度比较慢&#xff0c;我会上传网盘链接 githun下载img文件地址: https://git…

常见的 HTML 标准

常见的 HTML 标准 常见的 HTML 标准发布历史 HTML&#xff08;Hypertext Markup Language&#xff09;有多个版本和标准。以下是一些常见的 HTML 标准&#xff1a; HTML 2.0&#xff1a;于1995年发布&#xff0c;是 HTML 的第一个正式标准。HTML 3.2&#xff1a;于1997年发布…

自学Java要到什么程度才足够能力去实习和就业?

引言 Java&#xff0c;作为当今软件开发领域的主流编程语言之一&#xff0c;对于初学者而言&#xff0c;明确掌握到什么程度才能开始寻找实习和入职机会是至关重要的。这涉及到对Java知识体系的理解深度、技能掌握程度以及实际项目经验的积累。 本文将分别从实习和入职两个不…

SpringBoot @MockBean 导致ApplicationContext Reload带来的问题的解决方法

在基于SpringBoot的项目中&#xff0c;编写单元测试时&#xff0c;会遇到需要对一些被Spring容器管理的对象进行Mock的处理&#xff0c;但是这些对象可能被引用的比较多。这个时候可以使用 MockBean 来注释相关对象。 如下面的代码片段&#xff1a; package com.example.spri…

C语言如何实现⼆级指针对⼆维数组的操作?

一、问题 如何操作⼆维数组&#xff1f; 二、解笞 要更清楚地了解⼆维数组的指针&#xff0c;⾸先要掌握⼆维数组数据结构的特性。⼆维数组可以看成是元素值为⼀维数组的数组。假设有⼀个 3 ⾏ 4 列的⼆维数组a&#xff0c;它定义为&#xff1a; int a[3][4] {{1,2,3,4},{5,…

第三节课,功能2:开发后端用户的管理接口--http client -- debug测试

一、idea 中 Http client 使用 二、测试步骤&#xff0c;先进入主程序 2.1 先run &#xff0c;再debug 2.2 再进入想要测试的代码 2.2.1 进入测试的接口 三、程序逻辑 1&#xff09;用户注册逻辑&#xff1a;如果用户不存在再后端&#xff0c;看用户名&密码&校验码是…