Luogu3871 [TJOI2010]中位数 题解
题目链接
看到题解里好多大佬用二分,splay,树状数组,优先队列等高级数据结构,然而本蒟蒻实在是渣,所以只能用最简单的纯vector写。
(个人觉得比大佬们写的简单)
C++中stl表真的方便,其中向量vector支持数组中间插入:
v.insert(v.begin()+i,a);
/*
v.begin()指v数组头地址,v.begin()+i相当于v[i],a即插入的值
*/
先发出我普通数组纯暴力30分的代码来揭露普通数组的害处
//30分的烂代码就不多加注释了
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
long long m,n,a[110001];
string f;
int main(){
scanf("%lld",&n);
for(long long i=1;i<=n;i++)scanf("%lld",&a[i]);
scanf("%lld",&m);
for(long long i=1;i<=m;i++){
cin>>f;
if(f=="add")scanf("%lld",&a[++n]);//将数直接加入数组尾
else{
sort(a+1,a+n+1);//每次sort不超时才怪
if(n%2)printf("%lld\n",a[(long long)ceil(n/2.0)]);
else printf("%lld\n",min(a[n/2],a[n/2+1]));
}
}
}
废话完了可以开始正文了
首先读入向量数组,sort排序:
scanf("%lld",&n);
for(long long i=0; i<n; i++) {
scanf("%lld",&a); //读入a
v.push_back(a); //将a放入v中
}
sort(v.begin(),v.end()); //排序,保证v为单调递增
以下本题核心:
将数插入向量v中,普通数组只支持修改查询,插入需每次sort排序或使用手工链表,sort排序过慢,链表调试不够方便,于是vector便闪亮登场(此处应有掌声)。
读入数据a,从头访问vector,在第一个大于a的位置前插入b,这样可以保证vector一直为单调递增,不需每次排序。同时应记录vector的长度n(话说好像用v.size()调整一下貌似也可以),n初始值为原始vector的长度。代码:
scanf("%lld",&a);
n++; //v的长度++
for(int i=0; i<n; i++) { //从头访问
if(v[i]>a) { //一旦找到第一个比a大的元素
v.insert(v.begin()+i,a);//将a插入v中
break; //退出循环
}
}
访问处在中间位置的数。若序列长度为偶数,则指处在中间位置的两个数中较小的那个,由于本vector数组从v[0]开始,所以记录的长度n-1才为要访问的点,即vector中第n个值为v[n-1]:
if(n%2) //若为奇数
printf("%lld\n",v[(long long)ceil(n/2.0)-1]);
//奇数除以2不为整数
//但注意C++中整数除以整数恒得整数,所以要除以实数2.0
//而数组下标必须为整型,所以要强制类型转换
else
printf("%lld\n",min(v[n/2-1],v[n/2]));
//输出中间位置两个数中较小者
所以组合起来AC总代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<vector>
using namespace std;
long long a,m,n;
string f;
vector<long long>v;
int main() {
v.reserve(200010); //保留空间,使v最大长度为200010,节省内存
scanf("%lld",&n);
for(long long i=0; i<n; i++) {
scanf("%lld",&a);
v.push_back(a);
}
sort(v.begin(),v.end());
scanf("%lld",&m);
for(long long i=1; i<=m; i++) {
cin>>f; //读入字符串f
if(f=="add") { //若字符串f为add则插入v中
scanf("%lld",&a);
n++;
for(int i=0; i<n; i++) {
if(v[i]>a) {
v.insert(v.begin()+i,a);
break;
}
}
} else { //若f为mid输出中位数
if(n%2)
printf("%lld\n",v[(long long)ceil(n/2.0)-1]);
else
printf("%lld\n",min(v[n/2-1],v[n/2]));
}
}
return 0;
}
PS:纯向量模拟,由于存在遍历访问数组和sort排序,复杂度最好情况为O(nm),最差可到O(nmlogn),代码跑的比较慢,qwq
但是好理解就足够了,对吧(其实是数据太水了QWQ)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】