BUCT2024寒假集训 进阶训练赛 (十四) 部分题解

A [蓝桥杯2022初赛] 数位排序

按题目要求即可,注意使用快排,否则会出现TLE。

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
int a[1000010];
int f(int n);
void QuickSort_dig(int* a, int begin, int end)
{
	if (begin >= end)
		return;
	int key = a[begin];
	int piti = begin;
	int left = begin;
	int right = end;
		while (left < right)
		{
			while (left < right && ((a[right] >= key&&f(a[right])==f(key))||f(a[right])>f(key)))
			{
				right--;
			}
			a[piti] = a[right];
			piti = right;
			while (left < right && ((a[left] <= key&&f(a[left])==f(key))||f(a[left])<f(key)))
			{
				left++;
			}
			a[piti] = a[left];
			piti = left;
		}
		a[piti] = key;
	QuickSort_dig(a, begin, piti - 1);
	QuickSort_dig(a, piti + 1, end);
}
int f(int n)
{
	int x=0;
	while(n!=0)
	{
		x+=n%10;
		n/=10;
	}
	return x;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		a[i]=i+1;
	}
	QuickSort_dig(a,0,n-1);
	cout<<a[m-1]<<endl;
	return 0;
}

B [蓝桥杯2018初赛]全球变暖

题解(包括DFS,BFS的简单普及)

C 发工资

工资不变,故尽量用大额币张数少,从大到小依次除,模即可。

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
int f(int n)
{
	int t=0;
	t+=n/100;
	n%=100;
	t+=n/50;
	n%=50;
	t+=n/10;
	n%=10;
	t+=n/5;
	n%=5;
	t+=n/2;
	t+=n%2;
	return t;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,s=0;
	cin>>n;
	while(n--)
	{
		int a;
		cin>>a;
		s+=f(a);
	}
	cout<<s<<endl;
	return 0;
}

D 看病要排队

一直有IN,OUT故先结构体让优先度与编号绑定再使用队列根据相应的输入进行处理。

#include<iostream>
using namespace std;
string k,s;
int main()
{
    cin>>k>>s;
    for (int i=0;i<s.size();i++)
    {
        int t=(k[i%k.size()]&31)-1;
        s[i]=(s[i]&31)-t>0?s[i]-t:s[i]-t+26;
    }
    cout<<s<<endl;
    return 0;
}

E 6.3.2.1 电话网络

虽然但是,没做出来。下面是原题附带的题解。
题解
其使用到Tarjan算法,下面是相关知识链接(正在啃)
Tarjan算法

G 打怪兽version-3

秒杀技肯定秒大怪,所以就是读数据排序然后相加,只要后面几个被秒杀的不参与计算即可。

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a[200010];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	ll s=0;
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	sort(a,a+n);
	for(int i=0;i<n-m;i++)
	{
		s+=a[i];
	}
	cout<<s<<endl;
	return 0;
}

I 2.4.6黑盒子

除最开始外要求输出的都不是最小值,注意不可以使用单调队列,构造大顶堆小顶堆来完成。虽然是老题,但是至今还没做出来,所以代码都是搬的别人的

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int N=30010;
int n,m;
int a[N],b[N];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int j=1;j<=m;j++)
	    cin>>b[j];
     priority_queue<int >down;//大顶堆用于存储我们当前要求的第几小元素
     priority_queue<int ,vector<int >,greater<int > >up; 
    for(int i=1,j=1;i<=m;i++)
    {//根据b数组的元素,判读我们当前需要遍历b[i]个元素
    //其中j为a数组的指针
        
        while(j<=b[i])
        {//注意本循环过程中大顶堆始终保持其元素个数不变
        //即始终保持堆顶是当前的第几小
           if(down.empty()||a[j]>=down.top())
           	up.push(a[j]);
           //当大顶堆为空时,说明我们当前需要找到的是第一小的数
           //此时不需要插入,只需要在循环结束之后接受小顶堆的堆顶就行
           //当当前遍历到的数据大于大顶堆堆顶是第几小的性质
           //只有当当前元素小于大顶堆元素才会影响大顶堆元素当前第几小的性质
           else
           {//为保持大顶堆堆顶是第几小的性质,将大顶堆的堆顶弹出至小顶堆
           	//然后大顶堆在接受当前小的元素,这样大顶堆的堆顶就保持了当前第几小的性质
             up.push(down.top());
             down.pop();
             down.push(a[j]);
           }
           j++;//注意j指针要前移
        }	
        //循环结束之后,我们要输出的第几小的这个排序应该加1
        //所以只需要将小顶堆的堆顶弹出至大顶堆,就可以满足这个条件
        down.push(up.top());
        up.pop();
        cout<<down.top()<<endl;
    }
    return 0;
}

K 打怪兽version-4

找规律可以发现是1,3,3,7,7,7,7,15…
即第N个对应的是2^(N/2+1)-1;

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n,s=1;
	int t=0;
	cin>>n;
	while(n!=0)
	{
		t++;
		n/=2;
	}
	for(int i=0;i<t;i++)
	{
		s*=2;
	}
	cout<<s-1<<endl;
	return 0;
}

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值