2023河南萌新联赛第(二)场:A,D,E,G,I

A

A-自动收小麦机_2023河南萌新联赛第(二)场:河南工业大学 (nowcoder.com)

 

看到需要求和的时候,也别是这种范围不是那么小的,就要想到用前缀和来实现,先用前缀和将每个高度对应的小麦的数量求出来。

for(int i=1;i<=n;i++)
{
	cin>>a[i];
	sum[i]=sum[i-1]+a[i];
}

其次,我们要算出在每个格子上面放水的时候对应的小麦数量,在以后的查询中更加方便,减少时间复杂度,那么我们应该怎样求出每个高度对应的小麦数量呢,分为两种情况,第一种:当从该位置流经k个格子时,没有遇见比当前高度低的,也就是高度一样第二种:当从该位置流经k个格子时,遇见比当前高度低的。不难发现两种情况都出现了比当前高度低的字眼,那么我们是不是要求一下比当前高度低的位置的坐标呢,遇见比当前高度低的就记下它的坐标。那么这个问题解决了。

最后我们应该怎样算出每个位置的小麦数量呢?对于第一种情况,我们直接可以用当前位置的小麦数量减去流经k个位置到达的格子的小麦的数量,得到的不就是从当前位置流经k个格子之后的小麦数量。对于第二种情况:要先算出该位置到比它低的位置的小麦数量,也就是sum[i]-sum[flag],最后还要加上你降低高度之后又流经k个格子对应的最终小麦数量。

 代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll sum[100009],a[100009],h[100009],ans[100009];
int n,q,k;
void find()
{
	int flag=-1;
	for(int i=1;i<=n;i++)
	{
		if(i==1) ans[i]=sum[i];
		else
		{
			if(h[i]>h[i-1])
			flag=i-1;
			if(i-k<flag) //说明向前流k个格子的时候有比当前高度低的
			ans[i]=sum[i]-sum[flag]+ans[flag];
			else //没有比当前高度低的
			ans[i]=sum[i]-sum[i-k];
		}
		
	}
}
int main()
{
	
	cin>>n>>q>>k;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
	}
//	for(int i=1;i<=n;i++)
//	cout<<sum[i]<<endl;
	for(int i=1;i<=n;i++)
    {
    	cin>>h[i];
	}
	find();
	while(q--)
	{
		int y;
		cin>>y;
		cout<<ans[y]<<endl;
	}
	return 0;
}

D

D-固执的RT_2023河南萌新联赛第(二)场:河南工业大学 (nowcoder.com)

 计算收集的树枝的攻击力之和是否满足最低要求。

代码:

#include<bits/stdc++.h>
using namespace std;
int a[100009];
int main()
{
	int n,m;
	long long sum=0;
	cin>>n>>m;
	int f=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		sum+=a[i];
		if(sum>=m)
		{
			f=1;
			break;
		}
	}
	if(f) cout<<"YES"<<endl;
	else cout<<"NO"<<endl;
	return 0;	
} 

E

E-释怀的RT_2023河南萌新联赛第(二)场:河南工业大学 (nowcoder.com)

 

题目意思很好理解,就是往两边分别照亮a[i]个距离,看最后有几个格子被照亮,如果遇见一个数就往两边遍历看是否会被点亮是会超时的,我们可以先从左向右遍历,被照亮的标记一下,在从右向左遍历,被照亮的在标记一下,这样就会大大减少时间复杂度。

对于更新距离举一个例子:例如 0 1 5 0 0,刚开始遇到1,距离u为1,遍历到5时候u--,u为0,此时向右遍历的范围从之前的1变成了现在的5,所以距离要更新。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[1000009];
ll vis[1000009]; 
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	ll ans=0;
	//向右遍历一遍
	ll u=0;//距离 
	for(int i=1;i<=n;i++)
	{
		if(!vis[i]&&u)//没有被标记过并且遍历的距离不为0
		{
			ans++;
			vis[i]=1;
		}	
		u--;
		if(a[i]>u) u=a[i]; //遇见照亮范围更大的,更新距离的值
	} 
	//向左遍历一遍
	u=0;
	for(int i=n;i>=1;i--)
	{
		if(!vis[i]&&u)
		{
			ans++;
			vis[i]=1;	
		}	
		u--;
		if(a[i]>u) u=a[i];
	} 
	cout<<ans<<endl;
	return 0;	
} 

G

G-爬山_2023河南萌新联赛第(二)场:河南工业大学 (nowcoder.com)

 

因为缆车越高攀爬高度越低,符合二分单调性,计算过程中要开long long。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100009];
int n,p;
bool find(int h)
{
	ll sum=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i]>h)
		sum+=a[i]-h;
	}
	return sum*2>=p;
}
int main()
{
 	cin>>n>>p;
 	ll sum=0;
 	for(int i=1;i<=n;i++)
 	{
 		cin>>a[i];
		sum+=a[i]; 	
    }
    if(sum*2<p) //当缆车高度为0的时候还小于运动指标
    {
    	cout<<"-1"<<endl;
    	return 0;
	}

	int l=0,r=0x3f3f3f3f;//开的大一点
 	while(l<=r)
 	{
 		int mid=(l+r)/2;
 		if(find(mid)) l=mid+1;
		else r=mid-1;	
	}
	cout<<l-1<<endl;
	return 0;
}

 I

I-奶牛的寿命_2023河南萌新联赛第(二)场:河南工业大学 (nowcoder.com)

题目中说是交换次数不超过log2(n)+1次,其实也就是次数不超过十进制数转换为二进制数的位数,但是由于没有前导0,所以最多交换len-1次,所以这个次数没有影响。

想要减刑时间长,那么我们就让高位的1与0交换,首先我们要将输入的十进制数转换为二进制,接着开始交换,交换完毕之后将二进制数重新转换为十进制数即可。 

 代码:

#include<bits/stdc++.h>
using namespace std;
string dict = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string ten(long long n)  //十进制转 x 进制函数。 
{
	string ans = "";//将字符串为空
	while (n != 0) //模拟短除法。 
	{
		ans += dict[n % 2];
		n /= 2;
	}
	string t = "";  //倒取余数。
	for (int i = ans.size()-1; i >= 0; i--) 
    t += ans[i];
	
    return t; 
}

int main()
{
	long long n;
	cin>>n;
	string s;
	s=ten(n); 
    //cout<<s<<endl;
    long long len=s.size();
    long long t=0;
    for(int i=1;i<len;i++)
	{
		if(s[i]=='0')
		{
			s[i]='1';
			t++;	
		}	
	} 
	int j=1;//最高位0不用交换
	while(t--)
	{
		s[j]='0';
		j++;
	}
	//cout<<s<<endl;
	long long sum=0,k=1;
	for(int i=len-1;i>=0;i--)
	{
		sum+=(s[i]-'0')*k;
		k*=2;
	}
	cout<<n-sum<<endl;
	return 0;	
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值