中位数(树状数组+二分)

题目描述

某天cbyyx突发奇想给lyt出了一道题:给定序列a,b,保证|a|+|b|为奇数且小于1e6,给定q组询问,每次将a序列其中一个数修改或将b序列其中一个数修改,问每次操作后两序列合并后的中位数是多少,lyt觉得这个问题太简单并把它秒了,但lyt觉得这个题对新生来说有点困难,于是他简化问题如下:给定两个正整数n,m,再给定长度为n的正整数序列a, 保证n为奇数。接下来m行,每行两个正整数p, x。表示把a[p]修改为x。对于每次操作输出修改后的中位数。

输入描述:

第一行输入两个正整数n,m

第二行给定n个正整数表示序列a1a_{1}a1​~ana_{n}an​

接下来m行每行给定两个数p,x,表示将a[p]修改为x。

1<=n<=1e6,1<=m<=1e5
∀1<=i<=n,1<=ai<=1e6\forall1<=i<=n,1<=a_{i}<=1e6∀1<=i<=n,1<=ai​<=1e6
1<=x<=1e6

输出描述:

对于每次操作输出每次操作后序列的中位数的值。

示例1

输入

7 3
1 2 3 4 5 6 7
2 3
4 4
7 1

输出

4
4
3

中位数原来可以用树状数组来求!!!!受教了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int M=4e4+10;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
int minn=0x3f3f3f3f;
int maxn=0xc0c0c0c0;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int n,k,m;
int a[N],tr[N];
int lowbit(int x)
{
	return x&-x;
}
void add(int x,int y)
{
	for(int i=x;i<=N;i+=lowbit(i)) tr[i]+=y;
}
int sum(int x)
{
	int res=0;
	for(int i=x;i;i-=lowbit(i)) res+=tr[i];
	return res;
}
void solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		add(a[i],1);
	}
	int c=n/2+n%2;
	for(int i=0,p,x;i<m;i++)
	{
		cin>>p>>x;
		add(a[p],-1);
		add(a[p]=x,1);
		int l=1,r=1e6;
		while(l<r)
		{
			int mid=l+r>>1;
			int v=sum(mid);
			if(v>=c) r=mid;
			else l=mid+1;
		}
		cout<<l<<endl;
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	ll t=1;
//	cin>>t;
	while(t--)
	{	
		solve();
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值