Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final) (A B C D)

昨天打了一场Div 2,做了三题吧,赛后补了D,前四题都是思维题没什么算法,赛后跟群友讨论了下思路,感觉自己的方法都比较笨吧,再来梳理梳理思路,(其实总感觉自己打cf以及atcoder有的时候是乱搞出来的,自己不能给别人讲的很明白,还是慢慢练吧…毕竟自己思维一直不好)
A题
题解:感觉算是一个性质吧,就是如果我们找到一个n>=2的数,从这个数到2*n-2,这些数全部都是不能互相除尽的。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n,m;
int a,b;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=n*2;i<=4*n-2;i+=2)
		{
			if(i==2*n) cout<<i;
			else cout<<' '<<i;
		}
		cout<<endl;
	}
}

B题

思路:其实就是遍历字符串,如果是第一个1,那么它没有选择只能选择引爆,如果是之后的1,它有两种选择,一种是直接引爆,另一种是把它和前面一个1之间的零全部填上炸弹,然后取这两种的最小费用就可以了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n,m;
int a,b;
int s[N];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>a>>b;
		string s;
		cin>>s;
		int z=-10;
		int idx=0;
		long long ans=0;
		for(int i=0;i<s.size();i++)
		{
			if(s[i]=='1')
			{
				if(z<0) 
				{
				z=i;
				ans+=a;	
				}
				else
				{
					ans+=min(a,b*(i-z-1));
					z=i;
				}
			}
		}
		
		cout<<ans<<endl;
	}
}

C题

思路:C题就是我感觉跟大佬有差距的地方了,我用的真的是特别朴素的模拟,然而赛后其他很多人都是用的二分查找以及二分答案做出来的,据说这道题可以不用sort,那样的话算法复杂度会降低很多;其实就是说如果你用到sort,那么这道题复杂度一定是nlongn的,那样子你用模拟和二分对复杂度都是没影响的,但如果不用排序的话复杂度就会低了。我的思路就是用一个结构体存起来两个时间,然后按照快递的时间从大到小排序,因为我们最大时间取决于我们快递时间最长以及自己去取的时间,因而我们只要一直增大自己取的时间,减少最大快递时间,即可得到最短时间
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
ll t,n,m;
ll a[N],b[N];
struct node{
	ll x;
	ll y;
}nodes[N];
bool cmp(node h,node j)
{
	if(h.x==j.x)
	return h.y<j.y;
	else
	{
		return h.x>j.x;
	}
}
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		for(int i=1;i<=n;i++)
		{
			cin>>b[i];
		}
		for(int i=1;i<=n;i++)
		{
			nodes[i]={a[i],b[i]};
		}
		sort(nodes+1,nodes+1+n,cmp);
		ll ans=nodes[1].x;
		ll res=0;
		nodes[n+1].x=0;
		for(int i=1;i<=n;i++)
		{
			res+=nodes[i].y;
			if(res<=nodes[i+1].x)
			{
				ans=nodes[i+1].x;
			}
			else break;
		}
		cout<<min(res,ans)<<endl;
	}
}
D题
思路:比赛的时候想的是按照对称性,外层两个数的和要大于内层两个数的和,然后wa了,赛后看了别人的想法,明白了这只是充分条件,什么意思?也就是不满足这个条件也有能成立的,然后看了群友的想法:遍历数组,如果当前的数比下一个数大,就没问题,因为此时下一位数只需要从前面减就能减到0,而当当前数小于下一位时,那么下一位数就需要有一部分从后面减才行,此时我们用一个变量加上此时需要从后面减的值,即:a[i+1]-a[i],而后面的每一位都要大于这个变量,因为从后面减时他们也要被减,这样循环下来,如果整个数组都满足就能全都减为0了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=30005;
typedef long long ll;
ll s[N];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>s[i];
		}
		ll ans=0;
		bool jud=true;
		for(int i=1;i<=n-1;i++)
		{
			if(ans>s[i]) 
			{
				jud=false;
				break;
			}
			if(s[i+1]>s[i]) ans+=s[i+1]-s[i];
		}
		if(s[n]<ans) jud=false;
		if(jud) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	 } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值