2020年牛客算法入门课练习赛1完结

Posted 辉小歌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020年牛客算法入门课练习赛1完结相关的知识,希望对你有一定的参考价值。

感觉题挺不错的,自己也觉得做过很多题了,但是做这一套题还是有的题有些许不会。

第k小数【难度: 简单 / 快排】


https://ac.nowcoder.com/acm/contest/5773/A

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
int a[N],t,n,k;
inline int read()
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
        if (ch == '-')
            f = -1;
        ch = getchar();
    
    while(ch >= '0' && ch <= '9')
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    
    return x * f;

int main(void)

	t=read();;
	while(t--)
	
		n=read(); k=read();
		for(int i=1;i<=n;i++) a[i]=read();
		sort(a+1,a+n+1);
		printf("%d\\n",a[k]);
	
	return 0;

不平行的直线【难度: 简单 / 数学】


https://ac.nowcoder.com/acm/contest/5773/B
就是求不同的斜率的数量。

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int gcd(int a,int b) return b?gcd(b,a%b):a;
vector<PII>ve;
int n;
set<PII>st;
int main(void)

	cin>>n;
	for(int i=0;i<n;i++)
	
		int a,b; cin>>a>>b;
		ve.push_back(a,b);
	
	for(int i=0;i<ve.size();i++)
	
		for(int j=i+1;j<ve.size();j++)
		
			int a=ve[i].first,b=ve[i].second;
			int c=ve[j].first,d=ve[j].second;
			int s1=c-a,s2=d-b;	
			int temp=gcd(s1,s2);
			st.insert(s1/temp,s2/temp);
		
	
	cout<<st.size()<<endl;
	return 0;

丢手绢【难度: 一般 / 取尺法 双指针】


https://ac.nowcoder.com/acm/contest/5773/C
尺取法,用双指针维护,对于一个点我们的最大结果一定是尽可能的平分。

#include<iostream>
using namespace std;
int a[100010] = 0;

int main()
    int n;
    cin >> n;
    int l = 0, sum = 0;//l在前,i在后
    for(int i = 0; i < n; i++)
         cin >> a[i];
         sum += a[i];
         
     int temp = 0;//两者间的距离
     int ans = 0, jin;
     for(int i = 0; i < n; i++)
     
     	while(temp < sum / 2)
     	//l为前面的
     		temp += a[l % n];//l % n因为是一个圈,在l = n时 又从a[0]开始加起
     		l++;
     	
     	jin = min(temp, sum - temp);//sum可能为奇数,一般会向下取整,判断较小的那半圈
     	ans = max(ans, jin);//最大值
     	temp -= a[i];
     
     cout << ans << endl;
     return 0;

二分【难度: 中 / 知识点: 差分】


https://ac.nowcoder.com/acm/contest/5773/D
居然是差分,太秒了。数据范围很大,故直接用map来映射

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int inf=INT_MAX;
map<int,int>mp;
int n=0;
void insert(int l,int r)

	mp[l]++;
	mp[r+1]--;

int main(void)

	cin>>n;
	for(int i=0;i<n;i++)
	
		int a; char b;
		cin>>a>>b;
		if(b=='.') insert(a,a);//给a这个位置加1
		if(b=='+') insert(-inf,a-1);//给 [-inf,a-1] 这段区间加1
		if(b=='-') insert(a+1,inf-1); //给 [a+1,inf-1]这段区间加1 因为我们的结果是不大于inf的,故是inf-1
	
	int ans=-1e9,sum=0;
	for(auto i=mp.begin();i!=mp.end();i++)
	
		sum+=i->second;
		ans=max(ans,sum);
	
	cout<<ans<<endl;
	return 0; 

交换【难度: 中 / 求环】


https://ac.nowcoder.com/acm/contest/5773/E
数据范围很大故先离散化一下,再进行。
很经典的一个问题,我们可以用图论的思路来解决。
我们的最终目的是n个自环,cnt用来当前有几个环,n-cnt就是我们还需要的环数,即为答案。

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int s[N],temp[N];
int vis[N];
int n,cnt;
map<int,int>mp;
int main()

    cin>>n;
    for(int i=1;i<=n;i++) scanf("%d",&s[i]),temp[i]=s[i];
    sort(temp+1,temp+n+1);
    for(int i=1;i<=n;i++) mp[temp[i]]=i;
    for(int i=1;i<=n;i++) s[i]=mp[s[i]];//离散化
    for(int i=1;i<=n;i++)
    
        if(!vis[s[i]])
        
            for(int j=s[i];!vis[j];j=s[j]) vis[j]=1;
            cnt++;
        
    
    cout<<n-cnt;
    return 0;

以上是关于2020年牛客算法入门课练习赛1完结的主要内容,如果未能解决你的问题,请参考以下文章

22年牛客多校第三场(F的证明

2023年牛客基础训练营3-K

牛客竞赛语法入门班循环结构习题完结

IT互联网技术分享:《2020年 MySQL集群实战》网盘资源

牛客竞赛语法入门班循环结构习题完结

牛客竞赛语法入门班数组模拟枚举贪心习题未完结