桶-复习笔记

桶的概念

首先,弄明白什么是一个桶
在一个桶里面只有一种数据,用来表示这种数据的多少

image

上图为5个桶
有了一个桶,我们可以做到去重,排序,统计等基础操作

例1.1 Luogu P1554

首先,我们求每一个数位

while(x){
	int now=x%10;//当前数位
	x/=10;
}

我们使用一个长度为 \(n\) 的数组 tot 来表示 \(n\) 个桶

那么我们先输入 \(n,m\),从n枚举到m,对每一个数字单独计算

在计算时,我们把每一个数位上数字对应的桶的大小+1

具体见代码

void solve(int x){
	while(x){
		int now=x%10;
		tot[now]++;
		x/=10;
	}
}
signed main(){
	cin>>n>>m;
	for(int i=n;i<=m;i++){
		solve(i);
	}
	for(int i=0;i<=9;i++){
		cout<<tot[i]<<' ';
	}
	return 0;
}

同理,让我们完成二维桶 Luogu P1789三维桶 Luogu P5729

二维桶(没写完不要看):

点击查看代码
void calhuo(int x,int y){
	for(int i=x-1;i<=x+1;i++){
		for(int j=y-1;j<=y+1;j++){
			tot[i][j]++;
		}
	}
	tot[x+2][y]++;
	tot[x-2][y]++;
	tot[x][y+2]++;
	tot[x][y-2]++;
}
void calying(int x,int y){
	for(int i=x-2;i<=x+2;i++){
		for(int j=y-2;j<=y+2;j++){
			tot[i][j]++;
		}
	}
}
signed main(){
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		calhuo(x+2,y+2);
	}
	for(int i=1;i<=k;i++){
		int x,y;
		cin>>x>>y;
		calying(x+2,y+2);
	}
	int ans=0;
	for(int i=1+2;i<=n+2;i++){
		for(int j=1+2;j<=n+2;j++){
			if(tot[i][j]==0){
				ans++;
			}
		}
	}
	cout<<ans;
	return 0;
}

三维桶:

点击查看代码
void cal(int a1,int b1,int c1,int a2,int b2,int c2){
	for(int i=a1;i<=a2;i++){
		for(int j=b1;j<=b2;j++){
			for(int k=c1;k<=c2;k++){
				tot[i][j][k]++;
			}
		}
	}
}
signed main(){
	cin>>w>>x>>h;
	cin>>q;
	while(q--){
		int a,b,c,d,e,f;
		cin>>a>>b>>c>>d>>e>>f;
		cal(a,b,c,d,e,f);
	}
	int ans=0;
	for(int i=1;i<=w;i++){
		for(int j=1;j<=x;j++){
			for(int k=1;k<=h;k++){
				if(tot[i][j][k]==0){
					ans++;
				}
			}
		}
	}
	cout<<ans;
	return 0;
}

桶计数

我们在之前使用了桶标记,现在我们把标记转化为计数

例2.1 Luogu P1598

首先,读入是一个问题,我们使用getline读入4行字符串,getline会自动读至换行,对于每一个字符,我们标记他所在的桶++

输出也是问题,我们这里统计一个桶的最大值,从最大值往1枚举如果桶的计数超过了枚举的数量,就代表这里要输出一个星号

见代码:

signed main(){
	for(int j=1;j<=4;j++){
		string s;
		getline(cin,s);
		for(int i=0;i<s.size();i++){
			tot[s[i]]++;//桶计数
		}
	}
	int maxi=0;
	for(char i='A';i<='Z';i++){
		maxi=max(maxi,tot[i]);//最大值
	}
	for(int i=maxi;i>=1;i--){//枚举
		for(char j='A';j<='Z';j++){//枚举字母
			if(tot[j]>=i){
				cout<<"* ";
			}
			else{
				cout<<"  ";//没达到也有输出一个空格
			}
			
		}cout<<endl;
	}
	for(char i='A';i<='Z';i++){//别忘了最后还有一行
		cout<<i<<' ';
	}
	return 0;
}

桶排序

我们用桶标记了元素的数量,现在,可以利用这一情况进行桶排序

例3.1 Luogu P1138

目标是找第k小的整数,通过统计每个数字出现的次数,然后按顺序累加桶的计数。例如,若桶数组为cnt[0...9],则从0到9依次检查sum += cnt[i],当sum >=k时,当前i即为答案。具体实现需注意数字范围和初始化桶数组。

posted @ 2025-10-12 21:20  KK_SpongeBob  阅读(18)  评论(0)    收藏  举报