7.23 Codeforces Round 961 (Div. 2)

7.23 Codeforces Round 961 (Div. 2)

4Codeforces Round 961 (Div. 2)Jul/23/2024 22:35UTC+8108371

B1 Bouquet (Easy Version)

n种花,a数组是不同花花瓣数,m个币,可以买m个花瓣。花束中任何两朵花的花瓣数之差不能超过 1。最多买几个花瓣

思路

用数组,排序,从前往后,超了,减k,加k+1;

用栈更方便。

代码

 int a[200050];
void solve()
{
 	int n,m,ans=0,sum=0;
 	cin>>n>>m;
 	for(int i=1;i<=n;i++)
 	cin>>a[i];
 	sort(a,a+n+1);
 	int k=a[1],l=0,x=0;
 	for(int i=1;i<=n;i++)
 	{
 	 
 		if(a[i]>m) break;
 		if(a[i]-k<=1)
 		{
 			if(sum>m&&l==0)
 			continue;
 			if(a[i]==k)
 			l++,x=i;
 			sum+=a[i];
		 	while(sum>m)
		 	{
		 		if(l>0)
			 	sum-=k,l--;
			 	else
			 	sum-=a[i];
			 }
			 if(sum<=m)
			 ans=max(ans,sum);
		 }
	 	else
	 	{
	 		if(a[i]-a[i-1]==1)
	 		{
			 	k+=1;
				 i=x;
			 	sum=0;l=0;
			 }
			 else
			 {
			 	k=a[i];
			 	sum=a[i],l=1,x=i;
			 	ans=max(ans,sum);
			 }
		 }
	 	
	 }
	 
	 cout<<ans<<'\n';
}
signed main()
{
	IOS
	int t;
	cin>>t;
	while(t--)
	solve();
}

B2 Bouquet (Hard Version)

a数组放花瓣数,b数组放花的数量。最多买多少

思路

轻敌了,还想用栈,不断往里面存。写了三个代码,问题:

  • vector初始化,resize,再排序,0全放前面了
  • vector的insert用错了,应该是push_back
  • 这个思路出现的共同问题:bad_alloc,数据太大,push的太多了。

虽然错了,但看到别人更巧的代码。直接用map排序+对应b数组。也有点鸡兔同笼的感觉。

先尽可能选择a[i],剩余的用a[i+1];

在比较(h1,mp[k+1]-h2),最小值就是将a[i]换成a[i+1]的最大值

这里很巧妙的用min,max

代码

int a[N];
signed main()
{
    IOS
    int t;
    cin>>t;
    while(t--)
    {
       int n,m,ans=0;
    cin>>n>>m;
    map<int,int> mp;
    for(int i=1;i<=n;i++)
    cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        cin>>mp[a[i]];
    }
    for(auto [k,v] :mp)
    {
        int q=m;
        int h1=min(v,q/k);//k最多选择多少
        if(mp.count(k+1)!=0)
        {
         int h2=min(mp[k+1],(q-h1*k)/(k+1));//在h1基础上,h2最多多少
         int sum=min(q,min(h1,mp[k+1]-h2)+h1*k+h2*(k+1));
         ans=max(sum,ans);
        }
        else
        ans=max(ans,h1*k);
    }
    cout<<ans<<'\n';  
    }
    
}

C.平方

一个数组可以对任意位进行任意次平方,直到不会出现递减。最少进行多少次。

输入

第一行包含一个整数 t( 1≤t≤1000 ) - 测试用例的数量。随后是测试用例的描述。

对于每个测试用例,第一行包含一个整数 n 数组 a的大小。第二行包含 n( 1≤𝑛≤2⋅10^5 ) 个整数1≤𝑎𝑖≤10^6 )。

思路

又轻敌了,我还以为单纯从前往后遍历一遍呢,没仔细思考,不断平方,数据得多大。**就比如10001,10002,10003…,明明就差1,但还不得不平方。**我的思路实属有点冒犯这一道题啦。

题解上有个浮点数的,还有个整数的。后者更好理解。因为前者涉及到了很多数学上的转化,比如:去对数,有很多对数的公式转化。

我在其中还学到了个东西:

int eps = 1e-9;

1乘10的-9次方,这里表示极小(epsilon),接近于0的极限.

接下来再说整数法:

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
vector<int> v;
void solve() {
    int n;
	cin >> n;
	v.resize(n);
	for(auto &i:v)//加&,不然TLE
	cin>>i;
	for (int i = 1; i < n; i++) 
	if(v[i-1]>1&&v[i]==1)
	{
	    cout<<"-1\n";//特判
	    return ;
	}
	vector<int > ops(n, 0);//初始化
	for(int i=1;i<n;i++){
	    int f=v[i-1];
	    int  b=v[i];
	    int temp=0;
	    while(f!=1&&f*f<=b)//如果前面的数小,看一下能接受
	    temp--,f*=f;  //him进行几次平方
	    while(f>b) //如果大的话,看需要进行几次平方
	    temp++,b*=b;
	    ops[i]=max(0ll,ops[i-1]+temp);
	}
	int ans=0;
	for(auto i:ops)
	ans+=i;
	cout<<ans<<'\n';      
}

signed main() {
	 ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t; 
	cin >> t;
	while (t--)
		solve();

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值