10.11日常训练

这是训练第一周,时间有点没有把控好,后面有点赶,所以后面尽量会往前赶进度,题目总体不难算是比赛时都能写出来的程度,但是自己应该还是练的不够,多数还是要看解析。前段时间一直在忙一些杂事,没怎么碰代码,果然周赛做得一塌糊涂,日后还是要多加练习,ok话不多说,看一下这周的解析吧。

A - Game With Sticks

这道题直接最小值%2等于0就是A赢,反之就是M赢。

复制代码
int mi=min(n,m);
if(mi%2!=0)
cout<<"Akshat"<<endl;
else cout<<"Malvika"<<endl;

B - 社团招新

Description

小 L 是学校算法协会的成员。在今年的学校社团招新中,小 L 一共招收了 nn 个新成员,其中 nn 为偶数。现在小 L 希望将他们分到协会不同的部门。

算法协会共设有三个部门,其中第 ii (1≤i≤n1≤i ≤n ) 个新成员对第 jj (1≤j≤31≤j ≤3) 个部门的满意度为 ai,ja**i ,j 。定义一个分配方案的满意度为所有新成员对分配到的部门的满意度之和,也就是说,若将第 ii (1≤i≤n1≤i ≤n ) 个新成员分配到了第 di∈{1,2,3}d**i ∈{1,2,3} 个部门,则该分配方案的满意度为 ∑i=1nai,di∑i =1nai ,d**i。

小 L 不希望某一个部门的新成员数量过多。具体地,他要求在分配方案中,不存在一个部门被分配多于 n22n 个新成员。你需要帮助小 L 求出,满足他要求的分配方案的满意度的最大值。

Input

本题包含多组测试数据。

输入的第一行包含一个正整数 tt,表示测试数据组数。

接下来依次输入每组测试数据,对于每组测试数据:

  • 第一行包含一个正整数 nn,表示新成员的数量。
  • 第 i+1i +1 (1≤i≤n1≤i ≤n ) 行包含三个非负整数 ai,1,ai,2,ai,3a**i ,1,a**i ,2,a**i ,3,分别表示第 ii 个新成员对第 1,2,31,2,3 个部门的满意度。

这道题开始没看懂什么意思,后来看了看题解才明白,我们要看满意度的最大值,可以先把他顺序安排下去,排满意度最多的那个,然后记录总满意度之和。如果大于n/2,那么我们就要开始换了,换成满意度第二大的,并且要换差值最小的,这样我们可以满意度比较大,最后直到小于等于n/2。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<ll,ll>
#define fi first
#define se second
const ll N=1e6+6;
const int mod=1e9+7; 
//ll a[N],b[N];
struct node{
	int x,y,z;
};
void solve()
{
	int n;
	cin>>n;
	vector<node> a(n+1);
	vector<int> b(n+1);
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x>>a[i].y>>a[i].z;
	}
	int ans=0;
	int cnt1=0,cnt2=0,cnt3=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i].x>=max(a[i].y,a[i].z))
		ans+=a[i].x,cnt1++,b[i]=1;
		else if(a[i].y>=max(a[i].x,a[i].z))
		ans+=a[i].y,cnt2++,b[i]=2;
		else
		ans+=a[i].z,cnt3++,b[i]=3;
	}
	vector<int> s;
	for(int i=1;i<=n;i++)
	{
		if(cnt1>n/2&&b[i]==1)
		s.push_back(a[i].x-max(a[i].y,a[i].z));
		else if(cnt2>n/2&&b[i]==2)
		s.push_back(a[i].y-max(a[i].x,a[i].z));
		else if(cnt3>n/2&&b[i]==3)
		s.push_back(a[i].z-max(a[i].x,a[i].y));
	}
	sort(s.begin(),s.end());
	int i=0;
	while(cnt1>n/2)
	ans-=s[i++],cnt1--;
	while(cnt2>n/2)
	ans-=s[i++],cnt2--;
	while(cnt3>n/2)
	ans-=s[i++],cnt3--;
	cout<<ans<<endl;
}
signed main()
{
	IOS
	ll PPP=1;
	cin>>PPP;
	while(PPP--)
	solve();
	return 0;
}

C - Dragons

桐人卡在了他正在玩的MMORPG游戏的一个关卡里。想要继续闯关,他必须打败关卡里所有的 n 条龙。桐人和这些龙都有一个实力值,用整数表示。在两者对决时,胜负取决于实力值。桐人初始的实力值是 s。

如果桐人选择从第 i 条龙(编号为 1 ≤ i ≤ n )开始挑战,且桐人的实力值不大于这条龙的实力 x**i ,那么桐人就会输掉这场决斗,游戏结束。但如果桐人的实力值大于这条龙的实力,他就能打败它,并获得 y**i 点实力加成。

桐人可以按任意顺序挑战这些龙。请判断他能否在不输一场的情况下,打败所有龙,顺利通关。

输入格式

第一行包含两个用空格分隔的整数 s 和 n (1 ≤ s ≤ 104,1 ≤ n ≤ 103)。接下来有 n 行,第 i 行包含两个用空格分隔的整数 x**i 和 y**i (1 ≤ x**i ≤ 104,0 ≤ y**i ≤ 104),分别表示第 i 条龙的实力值和击败它后获得的实力加成。

这道题我们就直接排序,从小到大排序,如果够就加成,如果不够就直接NO输出,遍历结束输出YES。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
struct node
{
	int x,y;
};
bool cmp(node a,node b)
{
	return a.x<b.x;
}
void solve()
{
	int s,n;
	cin>>s>>n;
	vector<node> a(n+1);
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x>>a[i].y;
	}
	sort(a.begin(),a.end(),cmp);
	for(int i=1;i<=n;i++)
	{
		if(s>a[i].x)
		s+=a[i].y;
		else 
		{
			cout<<"NO"<<endl;
			return;
		}
	}
	cout<<"YES"<<endl;
}
signed main()
{
    IOS;
    int __=1;
    //cin>>__;
    while(__--)
    solve();
    return 0;
}

D - Puzzles

学年即将结束,班主任玛娜娜老师又要送别一届学生。她决定为班上的n名学生准备告别礼物------每人赠送一幅拼图(根据维基百科定义,拼图是一种需要将许多形状不规则的小块进行互锁拼接的益智游戏)。

店员告诉老师,店里现有m 款拼图,但难度和尺寸各不相同。具体来说,第一款有f 1片,第二款有f2片,依此类推。

玛娜娜老师不希望让孩子们感到不公平,因此决定让所选购拼图的片数差异尽可能小。设A 为老师购买的最大拼图片数,B 为最小拼图片数。她需要选择n 款拼图,使得A - B 的值尽可能小。请帮助老师计算出A - B的最小可能值。

输入

第一行包含空格分隔的整数n 和m (2 ≤ n ≤ m ≤ 50)。第二行包含m 个空格分隔的整数f 1, f 2, ..., f**m (4 ≤ f**i ≤ 1000),表示店内各款拼图的片数。

输出

输出一个整数,表示老师能够获得的最小片数差值。

这道题初看有点唬人,没看懂,也可能是我太菜了,后来看了题解发现很简单。就是直接排序,在m款里面选n款,我们一个一个来看,从1到n,再从2到n+1,一直到m;我们看差值得最小值,就是我们要的结果。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define int long long
void solve()
{
	int n,m;
	cin>>n>>m;
	vector<int> f(m+1);
	for(int i=1;i<=m;i++)
	cin>>f[i];
	sort(f.begin(),f.end());
	int ans=LLONG_MAX;
	for(int i=n;i<=m;i++)
	{
		ans=min(ans,f[i]-f[i-n+1]);
	}
	cout<<ans<<endl;
}
signed main()
{
    IOS;
    int __=1;
    //cin>>__;
    while(__--)
    solve();
    return 0;
}

E - Twins

想象一下,你有一个双胞胎兄弟或姐妹。身边有一个长得和你一模一样的人,听起来确实挺神奇。至于拥有一个"另一个自己"究竟是好事还是坏事,还真不好说。不过,如果你真的有双胞胎,那你肯定深有体会。

现在,让我们设想一个你家里再普通不过的早晨。你还在呼呼大睡,妈妈却已经急着去上班了。她忙得团团转,差点忘了给自己最心爱的两个孩子留上午餐费,好让你们去学校食堂吃饭。她翻了翻钱包,找出了一些硬币,准确地说,是 n 枚价值分别为 a 1, a 2, ..., a**n 的硬币。可妈妈实在赶时间,没来得及把硬币分给你们俩,只好潦草地写了张纸条,让你们平分这笔钱。

你醒来后,发现了妈妈留下的硬币和纸条。"为什么要平分呢?"------你这样想着。毕竟,双胞胎还在睡觉,什么都不会知道。于是你打算这么做:挑出一些硬币,使你拿到的硬币总价值 严格大于 剩下那些由双胞胎拿着的硬币总价值。不过,你也明白,拿太多硬币的话,双胞胎很可能会察觉不对劲。为了不引起怀疑,你决定采取如下策略:拿走总价值严格大于剩余硬币总价值的 最少数量的硬币。请你求出,按照这种方式分配时,你至少需要拿走多少枚硬币。

输入

第一行包含一个整数 n (1 ≤ n ≤ 100),表示硬币的数量。第二行包含 n 个整数 a 1、a 2、......、a**n (1 ≤ a**i ≤ 100),表示每枚硬币的价值。所有数字之间用空格分隔。

输出

在一行中输出一个整数,即所需拿走的最少硬币数量。

这道题也很简单,直接排序取反,然后开始遍历,判断是否大于sun/2,如果不大于,直接加上,继续判断,如果大于直接输出。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<ll,ll>
#define fi first
#define se second
const ll N=1e6+6;
const int mod=1e9+7; 
//ll a[N],b[N];
void solve()
{
	int n;
	cin>>n;
	int sum=0;
	vector<int> a(n);
	for(int i=0;i<n;i++) cin>>a[i],sum+=a[i];
	int num=sum/2;
	sort(a.begin(),a.end());
	reverse(a.begin(),a.end());
	int ans=0,cnt=0;
	for(int i=0;i<n;i++)
	{
		ans+=a[i];
		cnt++;
		if(ans>num)
		{
			cout<<cnt<<endl;
			return;
		}
	}
	//cout<<fixed<<setprecision(k);
}
signed main()
{
	IOS
	ll PPP=1;
	//cin>>PPP;
	while(PPP--)
	solve();
	return 0;
}

F - BerSU Ball

这道题周赛的时候也出了,当时没做出来。后来发现很简单,直接排序标记就可以了。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<ll,ll>
#define fi first
#define se second
const ll N=1e6+6;
const int mod=1e9+7; 
//ll a[N],b[N];
void solve()
{
	int n;
	cin>>n;
	int sum=0;
	vector<int> a(n);
	for(int i=0;i<n;i++) cin>>a[i],sum+=a[i];
	int num=sum/2;
	sort(a.begin(),a.end());
	reverse(a.begin(),a.end());
	int ans=0,cnt=0;
	for(int i=0;i<n;i++)
	{
		ans+=a[i];
		cnt++;
		if(ans>num)
		{
			cout<<cnt<<endl;
			return;
		}
	}
	//cout<<fixed<<setprecision(k);
}
signed main()
{
	IOS
	ll PPP=1;
	//cin>>PPP;
	while(PPP--)
	solve();
	return 0;
}

G - Buying Shovels

Polycarp 想买 正好 nn 把铲子。商店里卖的是装铲子的包。店里有 kk 种包:第 ii 种包里正好装 ii 把铲子(1≤i≤k1≤i ≤k)。每种包的库存无限。

Polycarp 想选 一种 包装类型,然后买若干个(至少一个)这种包。问他最少要买多少包,才能正好凑够 nn 把铲子?

举个例子,如果 n=8n =8,k=7k=7,那 Polycarp 会买 22 个装 44 把铲子的包。

帮 Polycarp 找出最少要买多少包,条件是:

  • 总共买的铲子数正好是 nn;
  • 买的所有包大小都一样,且每包铲子数是从 11 到 kk 之间的整数。

输入

第一行一个整数 tt (1≤t≤1001≤t ≤100)------ 输入中测试用例的数量。接下来 tt 行,每行一个测试用例。

每个测试用例包含两个正整数 nn (1≤n≤1091≤n ≤109)和 kk (1≤k≤1091≤k≤109)------ 铲子总数和包的种类数。

输出

输出 tt 行,每行一个正整数------对应测试用例的最小购买包数。

这道题之前觉得挺简单的,为什么不能直接一个一个算,最后发现会超时。所以我们可以进一步优化,如果n%i=0,那么n/i%i=0也是符合的,这样我们就可以循环减半,也就是sqrt(n)遍循环。我们要求最少买多少个包,就是求每个包最大装几把铲子,然后再去求最大值就可以了。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<ll,ll>
#define fi first
#define se second
const ll N=1e6+6;
const int mod=1e9+7; 
//ll a[N],b[N];
void solve()
{
	int n,k;
	cin>>n>>k;
	int mx=0;
	for(int i=1;i*i<=n;i++)
	{
		if(n%i==0)
		{
			if(i<=k)
			mx=max(mx,i);
			int shu=n/i;
			if(shu<=k)
			mx=max(mx,shu);
		}
	}
	cout<<n/mx<<endl;
	//cout<<fixed<<setprecision(k);
}
signed main()
{
	IOS
	ll PPP=1;
	cin>>PPP;
	while(PPP--)
	solve();
	return 0;
}

J - Potions (Hard Version)

这是本题的困难版本。与简单版本唯一的区别在于,本版本中 n≤200000*n*≤200000。只有在两个版本都通过的情况下,才能进行 hack。

一排摆放着 nn 瓶药水,最左边是第 11 瓶,最右边是第 nn 瓶。喝下第 aia**i 瓶药水后,你的生命值会增加 aia**i 。当然,aia**i 也可能是负数,这意味着喝下药水后生命值会减少。

一开始你的生命值为 00,随后你会从左到右、从第一瓶走到最后一瓶。经过每瓶药水时,你可以选择喝下它,也可以直接跳过。必须保证你的生命值始终不小于 0。

你最多能喝下多少瓶药水?

输入

第一行包含一个整数 nn (1≤n≤2000001≤n≤200000)------药水的数量。

第二行包含 nn 个整数 a1a 1、a2a 2、...、ana**n (−109≤ai≤109−109≤a**i≤109),表示喝下对应药水后生命值的变化量。

输出

输出一个整数,表示在生命值始终不变为负数的前提下,最多能喝下的药水数量。

这道题我们用到小根堆,依次累加,如果小于0,就把最小的减去,累加的结果也减去,总数-1,直到大于等于0,输出总数。

复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define int long long
#define ll long long
#define pii pair<int,int>
#define fi first
#define se second
#define BUG cout<<"debug"<<endl;
const int N=1e9+6;

void solve()
{
	int n;
	cin>>n;
	int hp=0,ans=0;
	priority_queue<ll,vector<ll>,greater<ll>> q;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		hp+=x;
		q.push(x);
		ans++;
		if(hp<0)
		{
			int t=q.top();
			q.pop();
			hp-=t;
			ans--;
		}
	}
	cout<<ans<<endl;
	// cout<<fixed<<setprecision(x)<<;
}
signed main()
{
	ll PPP=1;
	//cin>>PPP;
	while(PPP--)
	solve();
	return 0;
}
相关推荐
Code_Solitude1 小时前
c语言:关于qsoet函数知识点
c语言·数据结构·算法
Nil2081 小时前
leetcode 49字母异位分组
算法·leetcode·哈希算法
weixin_307779132 小时前
C++代码实现MATLAB中的spectralcluster函数功能
开发语言·c++·算法·matlab
行者全栈架构师2 小时前
【鸿蒙心迹】让应用“悬浮“起来——闪控球(floatingBall)从接入到实战全链路(HarmonyOS 7.x)
前端·算法·架构
云的雨 雨的云2 小时前
手写算法动画上位机:从排序到线性代数可视化
线性代数·算法
Pniubi2 小时前
快速排序(力扣基础)(递归)
java·数据结构·算法
roman_日积跬步-终至千里2 小时前
【数据Agent论文·分析与报告评测|27】ComInsight:原子洞察正确,组合后的结论就可靠吗?
人工智能·算法·机器学习·数据分析
Samson Bruce3 小时前
【数学之美】
线性代数·算法·概率论
Mister Leon3 小时前
Nvidia Orin AGX实战之从量化到蒸馏:在 Orin 上落地的大模型压缩实战
人工智能·算法·机器学习