第二次个人训练赛 2019/11/19

本文解析了LeetCode第二次训练赛的多个题目,包括求离原点最远坐标、连续子串划分、模运算求和、怪物战斗、折扣券最优分配等,通过详细代码和思路阐述了解题方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第二次训练赛

leetcode上的题目

A - Engines
在这里插入图片描述
在这里插入图片描述

题意:

给定n个点的坐标,你可以按照任意顺序,把坐标值加到一块,每一个坐标最多用一次(每一个坐标可以使用一次,或者不使用),要求得到的坐标值离原点最远。

思路:

将每一个点当作一个向量的坐标,两个向量相加,夹角越小,想加形成的向量和的模长越长。
所以,可以将这些向量按照极角排序

#include<bits/stdc++.h>
#include<cmath>
using namespace std;
typedef long long ll; 
const int N = 110;
struct node{
	ll x,y;
}r[N];
//ll nx[N];

bool cmp(node a,node b)
{
	return atan2(a.y,a.x)<atan2(b.y,b.x);
}
int main()
{
	ll n;
	cin>>n;
	for(ll i=1;i<=n;i++) cin>>r[i].x>>r[i].y;
	sort(r+1,r+n+1,cmp);
	ll nx[N];//用于循环 
	for(ll i=1;i<=n;i++) nx[i]=i+1;
	nx[n]=1;
	ll ans=0;
	for(ll i=1;i<=n;i++)
	{
		ll X=r[i].x,Y=r[i].y;
		ans=max(ans,X*X+Y*Y);
		for(ll j=nx[i];j!=i;j=nx[j])
		{
			X+=r[j].x;
			Y+=r[j].y;
			ans=max(ans,X*X+Y*Y);
		}
	}
	printf("%.10lf\n",sqrt(ans));
	return 0;
}

B - Consecutive Integers

题意:

给定一个长度为n的数列,将这个数列分成连续并且长度为k的子串
问?最多能分出多少个这样的子串

思路:

总共n-k+1个

#include<bits/stdc++.h>

using namespace std;

int main()
{
	int n,k;
	cin>>n>>k;
	cout<<n-k+1<<endl;
	return 0;
 } 

C - ModSum

题意:

给定一个整数n,从1~n建立一个数组 a[i]=i;
对这个数组重新排序,使得 数值%下标的和最大

思路:

数值:13 1 2 3 4 5 6 7 8 9 10 11 12
下标:1 2 3 4 5 6 7 8 9 10 11 12 13
结果最大为:0+1+2+3+4+5+6+7+8+9+10+11+12;

这个题走了很多坑
刚开始用暴力写出了结果,但是n的数值1e9 所以超时了
结果又想了很多种什么时候取得最大的情况,但是多错了
最后我用暴力写出的代码得到了重新排列后的数组,然后得知上诉情况取得最大值。

错误代码
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 0x3f3f3f3f;
bool vis[N];
int main()
{
	ll n;
	cin>>n;
	ll ans=0;
	for(ll i=1;i<=n;i++)
	{
		ll mod=0;
		for(ll j=1;j<=n;j++)
		{
			if(!vis[j]) 
			{
				if(i%j>mod)
				{
					vis[j]=1;
					mod=i%j;
				}
			} 
		}
		ans+=mod;
	}
	cout<<ans<<endl;
	return 0;
}

正确代码

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1e9+10;
int main()
{
	ll n;
	cin>>n;
	ll ans=0; 
	for(int i=1;i<=n-1;i++)
		ans+=i;
	cout<<ans<<endl;	
	return 0;
}

F - Monsters Battle Royale

题意:

给出n个怪物的生命值, 一个随机的活的怪物攻击另一个随机的活的怪物。
被攻击的生命值的减少量等于当前正在攻击的怪物的生命值,而攻击者的生命值不变.

思路:

求出n个数的GCD

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 100010;
int a[N];
int main()
{
	int n;
	cin>>n;
	int gcd;
	int x;
	cin>>x;
	gcd=x;
	for(int i=2;i<=n;i++) 
	{
		cin>>x;
		gcd=__gcd(gcd,x);
	}
	cout<<gcd<<endl;
	return 0;
}

G - Powerful Discount Tickets

题意:

有n个商品,有m张打折券,打折的具体规定为 :物品单价X,打折券的个数为Y, 打完折后物品的单价为 X/2^Y;
这m张打折券如果分配,最后n个商品的总价格最低

思路:

从最高的价格进行打折,最高价格的商品打完折后的价格为X=Xmax/2, 对最高的价格用一张券,每次都更新这n个商品的价格,每次都选择当前商品价格最高的商品进行打折券的使用.

运用优先队列(从大到小排列)进行存放物品的单价,每次取队首/=2,在将其压进队列,重复此操作,一直到m张打折券用完.

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
//每次都选出最大的那一个数除以2 
int main()
{
	int n,m;
	ll ans=0;
	cin>>n>>m;
	priority_queue<int>que;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		que.push(x);
	}
	for(int i=0;i<m;i++)
	{
		que.push(que.top()/2);
		que.pop();
	}
	while(!que.empty())
	{
		ans+=que.top();
		que.pop();
	}
	cout<<ans<<endl;
	return 0;
}

H - Attack Survival

题意:

n,k,Q
给定一个长度为n的数组a[n],并且所有的值都为k,
输入k个数,这k个数是数组的下标,说明:::当k个数中的其中一个数为2时,说明a[2]不变,其他的数值都减一。
if a[i]的值<=0 输出“NO”;
else 输出“Yes”:

思路:

记录k个数的每一个数的个数 ,得到 k-(Q-mp[i])进行判断

#include<bits/stdc++.h>

using namespace std;
const int N =100010;
int b[N];
int vis[N];
int main()
{
	int n,k,q;
	cin>>n>>k>>q;
	memset(vis,0,sizeof(vis));
	int id;
	for(int i=1;i<=q;i++) cin>>id,vis[id]++;
	for(int i=1;i<=n;i++) 
	{
		b[i]=k;
		b[i]=b[i]-(q-vis[i]);
		if(b[i]>=1)	puts("Yes");
		else puts("No");	
	}
	return 0;
}

I - Lower

题意:

给定一个长度为n的数组,每一个数值当作楼梯的高度,如果后边的数值小于当前的数值,则前进一步,问::最多能前进几步?

思路:

从左往右进行遍历,每次都更新找到最大的step。

注意:如果后面几个楼梯的高度都能往下走,最后必须要记录最后的那个走的步数进行step(max)的选取。
因为只有走到右边的数大于当前的数,才会停止得到当前的res,最后一直走下去则找不到最后的res,所以,要进行一个记录。

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 100010;
ll a[N];
bool b[N];
int main()
{
	ll n;
	cin>>n;
	a[0]=0;
	ll ans=0;
	ll res=0;
	for(ll i=1;i<=n;i++)
	{
		cin>>a[i];
		if(a[i]>a[i-1])
			b[i]=0;
		else
			b[i]=1;	
	}
	ll flag=0;
	for(ll i=1;i<=n;i++)
	{
		if(b[i]) 
		{
			res++;
			flag=res;
		}
		else
		{
			ans=max(ans,res);
			res=0;
		}
	}
	cout<<max(ans,flag)<<endl;
	return 0;
}

J - Kleene Inversion

题意:

给定一个长度为n的数组,并且复制k次,如果前面的数大于右边的数就ans+=1;求得最后的ans

思路:

在长度为n的数组中,找到当前位置右边的数小于当前位置数的个数,左边的数大于当前位置的数的个数。

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 10000;

ll a[N]; 
ll r[N],l[N];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	ll n,k,ans;
	cin>>n>>k;
	for(ll i=1;i<=n;i++) cin>>a[i];
	ll num=0;
	num=(k+1)*k/2;
	num-=k;
	num%=mod;
	ans=0;
	memset(r,0,sizeof(r));
	memset(l,0,sizeof(l));
	for(ll i=1;i<=n;i++)
	{
		for(ll j=1;j<i;j++)
		{
			if(a[i]>a[j])
				l[i]++;//这个数左边小于当前位置的数的个数 
		}
		for(ll j=i+1;j<=n;j++)
		{
			if(a[i]>a[j])
				r[i]++;//这个数右边小于当前位置的数的个数 
		}
	}
//	cout<<num<<endl;
	for(ll i=1;i<=n;i++)
	{
//		cout<<l[i]<<' '<<r[i]<<endl;
		ans=ans+l[i]*num%mod;
		ans=ans+r[i]*(num+k)%mod;
	}
	cout<<ans%mod<<endl;	
	return 0;
}

M - AB Substrings

题意:

将n个字符串组成一个字符串,问如何分配才能得到最多的含有“AB”的个数?

思路:

求得a=······A,b=B·····字符串的个数,res=min(a,b),在求出每一个字符串中含有“AB”的个数进行加和。

注意:
当两个字符串都为 B····A,则最后的答案为1
所以要将这种特殊情况在最后的答案中减去1

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N= 100100;
string s[N];
//map<int,map<char,char>>mp;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	ll n;
	cin>>n;
	int t;
	ll res;
	map<char,ll>m;
	map<char,ll>p;
	int flag=0;
	for(ll i=0;i<n;i++) 
	{
		cin>>s[i];
		m[s[i][0]]++;
		p[s[i][s[i].size()-1]]++;
		if(s[i][0]=='B'&&s[i][s[i].size()-1]=='A')
			flag++;
	}
	ll a=m['B'],b=p['A'];
	ll c=a-flag,d=b-flag;
	ll ans=0;
	for(ll i=0;i<n;i++)
	{
		t=s[i].size();
		for(ll j=0;j<t;j++)
		{
			if(s[i][j+1]=='B'&&s[i][j]=='A')
				ans++;
		}
	}
	res=min(b,a);
	ans+=res;
//	cout<<flag<<endl;
//	cout<<ans<<endl;
	if(c==0&&d==0&&flag!=0) ans--; //当给定的字符串中都是以B开头  以A结尾的字符串,最后的结果需要减去1 
	cout<<ans<<endl;
	return 0;
 } 
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值