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完结的主要内容,如果未能解决你的问题,请参考以下文章