【OI赛第三场t2】雇佣妹抖

小天使在新开的妹抖咖啡厅面临雇佣妹抖的挑战。他需要根据妹抖的能力值和帮派关系,处理关于招聘帮派的查询。通过树状数组,解决连续妹抖段数的统计问题,实现离线处理并降低时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【问题描述】
小天使新开了一家妹抖咖啡厅,所以他需要雇佣若干妹抖。
现在有n个妹抖,第i个妹抖有能力值Ai。
小天使想要招募一些能♂干的妹抖,他每次会招募所有能力值大于等 于B的妹抖,然而妹抖之间也会拉帮结派,对于两个被招募的妹抖i和妹 抖j,他们属于同一派的充要条件是:对于所有k ∈ [i,j],妹抖k被招募了。 现在小天使有Q次操作,每次操作是以下两种之一:
(1).给定B,求招募所有能力大于等于B的妹抖的话,他们会分成几个 帮派。
(2).给定C,D,将AC修改成D。

【输入格式】
第一行两个正整数n,Q。
接下来n行,每行一个整数表示Ai。
接下来Q行,每行第一个整数T表示操作类型:
(1).若T = 1,给定B,表示操作(1)
(2).若T = 2,给定C,D,表示操作(2)
【输出格式】
对于每次询问输出答案。

题解

相当于统计有几段连续的妹抖能力都大于等于B。 可以发现,一段连续的长为L的妹抖,贡献了(L−1)对相邻的妹抖。 于是我们只要计算(总的被选中的妹抖的个数) - (有几对相邻的妹抖被 选中了)就可以算出段数了。用两个树状数组维护,当进行单点修改时,(总的被选中的妹抖的个 数)显然是很容易维护的,(有几对相邻的妹抖被选中了)只要把每相邻两个 妹抖的能力值的最小值插入到树状数组就可以维护了。由于能力值较大,所以得离线先离散好能力值才能用树状数组维护。注意离散的时候要先把所有的询问先读进来,否则离散就没有意义了,没法加入新值,时间复杂度:O(Qlogn)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=400010;
int n,qq,B,c,d,d1,T,num;
int a[maxn],b[maxn],t[maxn],tr[maxn],q[maxn][3];
int lowbit(int x){
	return x&(-x);
}
void add1(int x,int y){//算有几个妹抖符合条件   
	for(int i=x;i<=num;i+=lowbit(i))    //change
	t[i]+=y;
}
void add2(int x,int y){//有几对相邻的妹抖被选中 
	for(int i=x;i<=num;i+=lowbit(i))//开到最大树状数组值 
	tr[i]+=y;
}
int find1(int x){
	int ans=0;
	for(int i=x;i>=1;i-=lowbit(i))
	ans+=t[i];
	return ans; 
}
int find2(int x){
	int ans=0;
	for(int i=x;i>=1;i-=lowbit(i))
	ans+=tr[i];
	return ans; 
}
int main(){
	scanf("%d%d",&n,&qq);
	for(int i=1;i<=n;i++){
	    scanf("%d",&a[i]);
	    b[i]=a[i];
	}
	int cnt=n;
	for(int i=1;i<=qq;i++){
		scanf("%d",&T);
		if(T==1) scanf("%d",&q[i][1]);
		else{
			scanf("%d%d",&q[i][0],&q[i][1]);	
		}
		b[++cnt]=q[i][1];   
	}
	sort(b+1,b+cnt+1);
	num=unique(b+1,b+cnt+1)-b-1;
	for(int i=1;i<=n;i++){
		a[i]=lower_bound(b+1,b+num+1,a[i])-b;
		add1(a[i],1);
	}
	for(int i=1;i<n;i++)
	add2(min(a[i],a[i+1]),1);
	
	for(int i=1;i<=qq;i++){ 
		if(q[i][0]==0){
			int B1=lower_bound(b+1,b+1+num,q[i][1])-b;
			int ans=n-find1(B1-1)-(n-1-find2(B1-1));
			printf("%d\n",ans);
		}
		else{
			c=q[i][0];
			d=lower_bound(b+1,b+num+1,q[i][1])-b;
			add1(a[c],-1);
			
			if(c>1)
			add2(min(a[c],a[c-1]),-1),add2(min(d,a[c-1]),1);
			if(c<n)
			add2(min(a[c],a[c+1]),-1),add2(min(d,a[c+1]),1);
			
			a[c]=d;
			add1(a[c],1); 
		}
	}
	return 0;
}
/*
5 4
8
6
3
5
4
1 5
2 4 1
1 5
1 3


*/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值