目录
一.运用的代码
二.思路详细讲解
三.代码辅助思考
题目传送门
一.运用的代码
这道题的主要思想是二分,先把二分模板提供给大家(相信大家已经不会看我这个蒟蒻发的模板了)
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;
}
如果各位觉得我写的不错的画,给个小小的赞和关注呗~