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)

posted @ 2019-05-26 15:20  TinyKiecoo  阅读(122)  评论(0编辑  收藏  举报