洛谷P9050《 Sumy》详细题解

本文详细讲解了一道编程题目,涉及二分查找算法、结构体定义、体重和位置排序,以及如何通过check函数判断鱼的存活状态。通过代码实例展示了如何按原顺序输出活到最后的鱼。
摘要由CSDN通过智能技术生成

目录

一.运用的代码

二.思路详细讲解

三.代码辅助思考


题目传送门

一.运用的代码

        这道题的主要思想是二分,先把二分模板提供给大家(相信大家已经不会看我这个蒟蒻发的模板了)

while(l<=r){
		mid=(l+r)/2;//取中间值
		if(check(mid)){//check函数要自己写哦~
	 		r=mid-1;//缩小寻找范围-------|
		}else{//                        |二者可互换位置
			l=mid+1;//缩小寻找范围,too__|
		}
	}

二.思路详细讲解

        本题是一个类似于“大鱼吃小鱼,小鱼吃虾米,虾米吃NOI”的题,一条鱼有三种属性(体重,原位置,是否能作为活到最后的鱼),所以我们需要定义一个结构体

​
struct node{
	int kg;//鱼的体重
	int id;//排序前的位置
	char TN;//能否作为活到最后的鱼
};

​

大家肯定知道二分基础是排序,而题目要求我们按原顺序输出,所以我们需要写两个cmp函数,一个对鱼的体重排序,另一个对fish的原位置排序,因为我们第一次用体重排完后会打乱顺序,后面还要再排回来。(代码如下)

//一开始用体重排序 
bool cmp(node a,node b){
	return a.kg<b.kg;
}
//后来用位置重新排序 
bool cmp1(node a,node b){
	return a.id<b.id;
}

接着我们就可以开始输入了(一道题中最简单的部分)可以拿一个数组存储,相信大家不会喜欢看我这个蒟蒻的代码了。

接着二话不说拿体重排序

	//排序(体重) 
	sort(a+1,a+1+n,cmp); 

接着我们愉快的套二分模板就可以了

//二分模板 
	while(l<=r){
		mid=(l+r)/2;
		//左零右一 
		if(check(mid)){
	    	r=mid-1;
		}else{
			l=mid+1;
		}
	}

注意这个未定义的check,它可是这个代码的核心部分,我们要算每条🐟能否吃掉别的所有鱼,当然,先吃比自己体重小的,再逐渐吃比自己体重大的🐟,如果能遍历完就说明成功了,二分就分原体重比自己小的鱼,否则就分原体重比自己大的鱼。没甚莫好说的,代码+注释辅助理解——

​
//check函数 
bool check(long long mid){
	//鱼体重 
	long long g=a[mid].kg;//不开long long 见祖宗
	//每条鱼遍历一遍 
	for(int i=1;i<=n;i++){
		//不吃自己 
		if(i==mid){
			//cerr<<i<<endl;
			continue;
		}else{//吃别的鱼
		//如果吃得了就吃了(增加体重) 
			if(g>a[i].kg) g+=a[i].kg;
			//吃不了那就肯定活不到最后 
			else return false;
		}
	}
	//都给吃了那就是活到了最后 
	return true;
}

​

接着我们就找到了分界线,1-r的鱼是活不到最后的,l-n的鱼是可以活到最后的,所以活不到最后的鱼它的属性TN就给N,活到最后的鱼它的属性TN就给T(已经1160个字了,作者仿佛看到了胜利的曙光)

//活不下去的给'N'  
	for(int i=1;i<=r;i++){
		a[i].TN='N';
	}
	//活下去的给'T' 
	for(int i=l;i<=n;i++){
		a[i].TN='T';
	}

别忘了再按原顺序排回来

	//排回原来的位置 
	sort(a+1,a+1+n,cmp1);	

最后一个个输出就可以了

	//从1到n输出 
	for(int i=1;i<=n;i++){
		cout<<a[i].TN;
	}

三.代码辅助思考

上代码

#include<bits/stdc++.h>
using namespace std;
/*放抄袭标签*/
//定义结构体 
struct node{
	int kg;
	int id;
	char TN;
};
//一开始用体重排序 
bool cmp(node a,node b){
	return a.kg<b.kg;
}
//后来用位置重新排序 
bool cmp1(node a,node b){
	return a.id<b.id;
}
const int N = 5e5+50;
//n条鱼 
int n;
//体重
node a[N];
//二分定义
long long mid,l=1;
//check函数 
bool check(long long mid){
	//鱼体重 
	long long g=a[mid].kg;
	//每条鱼遍历一遍 
	for(int i=1;i<=n;i++){
		//不吃自己 
		if(i==mid){
			//cerr<<i<<endl;
			continue;
		}else{//吃别的鱼
		//如果吃得了就吃了(增加体重) 
			if(g>a[i].kg) g+=a[i].kg;
			//吃不了那就肯定活不到最后 
			else return false;
		}
	}
	//都给吃了那就是活到了最后 
	return true;
}
int main(){
	//输入流 
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].kg; 
		//存储原先的位置,方便以后再排回来 
		a[i].id=i;
	}
	//定义r 
	int r=n;
	//排序(体重) 
	sort(a+1,a+1+n,cmp); 
	//二分模板 
	while(l<=r){
		mid=(l+r)/2;
		//左零右一 
		if(check(mid)){
	    	r=mid-1;
		}else{
			l=mid+1;
		}
		//cerr<<l<<endl;
	}
	//活不下去的给'N'  
	for(int i=1;i<=r;i++){
		a[i].TN='N';
	}
	//活下去的给'T' 
	for(int i=l;i<=n;i++){
		a[i].TN='T';
	}
	//排回原来的位置 
	sort(a+1,a+1+n,cmp1);	
	//从1到n输出 
	for(int i=1;i<=n;i++){
		cout<<a[i].TN;
	}
	return 0;
}

如果各位觉得我写的不错的画,给个小小的赞和关注呗~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值