树状数组与离散化与求第K大模板

树状数组模板:

//Cnt为数组的界
//cnt[i]为编号或者数值上小于id的数量
void Update(LL Id)
{
	while(Id<=Cnt)
	{
		cnt[Id]++;
		Id+=lowbit(Id);
	}
}
LL num(LL Id)
{
	LL ans=0;
	while(Id>0)
	{
		ans+=cnt[Id];
		Id-=lowbit(Id);
	}
	return ans;
}

离散化

//arr为保存原数据的数组
//id为保存新的ID的数组
sort(arr+1,arr+1+n);
Cnt=unique(arr+1,arr+1+n)-arr-1;
for(LL i=1;i<=n;i++) id[i]=lower_bound(arr+1,arr+1+Cnt,p[i].x)-arr;

求第K大的模板

void add(int x,int val)
{
	while(x<size)
	{
		c[x]+=val;
		x+=lowbit(x);
	}
}
int sum(int x)
{
	int ans=0;
	while(x)
	{
		ans+=c[x];
		x-=lowbit(x);
	}
	return ans;
}
//以上为树状数组的常规代码
int query(int k)
{
	int ans=0,cnt=0;
	for(int i=20;i>=0;i--)
	{
		
		ans+=(1<<i);
//这里使用了二进制的思想,去卡那个目标的第k大,当ans小于第K大时,ans就会增加,当ans大于等于第K大
//时,ans就放弃这次增加,这样最后得到的ans必然是第K大-1
		if(ans>=maxn||cnt+c[ans]>=k)
		{
			ans-=(1<<i);
		}
		else
		{
			cnt+=c[ans];
		}
		
	}
	return ans+1;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值