ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P3871 [TJOI2010]中位数

2022-09-12 10:02:44  阅读:153  来源: 互联网

标签:le int siz points 中位数 TJOI2010 P3871 SIZE


简要题意

你需要维护一个初始长度为 \(N\) 的序列 \(A\),有 \(M\) 个操作,支持:

  • add a 在 \(A\) 末尾插入一个数 \(a\)。
  • mid 求 \(A\) 的中位数中位数是指将一个序列按照从小到大排序后处在中间位置的数。(若序列长度为偶数,则指处在中间位置的两个数中较小的那个)

\(1 \le N \le 10^5,0 \le M \le 10^4\),保证任意时刻 \(|A_i|,|a| \le 10^{9}\)。

思路

不难发现,如果 \(A\) 是有序的,长度为 \(N\) 的序列,那么 \(A\) 的中位数 \(A_m\) 满足:

\[m={\lfloor \frac{N+1}{2} \rfloor} \]

维护有序的序列,当然选用平衡树啦。这里用的是 \(\text{FHQ - Treap}\)。

代码

#define int long long
using namespace std;

namespace FHQTreap{
	const int SIZE = 2e5+5;
	int son[SIZE][2];
	int val[SIZE],rk[SIZE],siz[SIZE],root,points;
	mt19937 randomer(time(0));

#define ls(i) (son[(i)][0])
#define rs(i) (son[(i)][1])

	void pushup(int i){
		siz[i]=siz[ls(i)]+siz[rs(i)]+1;
	}

	int newnode(int v){
		val[++points]=v;
		rk[points]=randomer();
		siz[points]=1;
		return points;
	}

	void split(int p,int v,int &left,int &right){
		if(!p){
			left=right=0;
			return;
		}
		if(val[p]<=v){
			left=p;
			split(rs(p),v,rs(left),right);
		}
		else{
			right=p;
			split(ls(p),v,left,ls(right));
		}
		pushup(p);
	}

	int merge(int left,int right){
		if(!left||!right){
			if(left)return left;
			else if(right)return right;
			else return 0;
		}
		if(rk[left]<rk[right]){
			ls(right)=merge(left,ls(right));
			pushup(right);
			return right;
		}
		else{
			rs(left)=merge(rs(left),right);
			pushup(left);
			return left;
		}
	}

	void insert(int v){
		int left=0,right=0;
		split(root,v-1,left,right);
		root=merge(merge(left,newnode(v)),right);
	}
	int kth(int k){
		int now=root;
		while(1){
			if(k<=siz[ls(now)]){
				now=ls(now);
			}
			else if(k==siz[ls(now)]+1){
				return val[now];
			}
			else{
				k-=siz[ls(now)]+1;
				now=rs(now);
			}
		}
	}
}

namespace solution{
	int n,m;
	int solution(){
		cin>>n;
		for(int i=1,v;i<=n;i++){
			cin>>v;
			FHQTreap::insert(v);
		}
		cin>>m;
		while(m--){
			string op;
			int m;
			cin>>op;
			if(op=="add"){
				cin>>m;
				FHQTreap::insert(m);
				n++;
			}
			else{
				cout<<FHQTreap::kth((n+1)/2)<<'\n';
			}
		}
		return 0;
	}
}

signed main(){
	return solution::solution();
}

标签:le,int,siz,points,中位数,TJOI2010,P3871,SIZE
来源: https://www.cnblogs.com/zheyuanxie/p/p3871.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有