2020年牛客算法入门课练习赛1 题解
前面的话:由于菜鸡实力有限+粗心,可能出现诸多错误或者是难以理解的地方,欢迎各位大佬指出,非常感谢
A 第k大数
可惜sort会被卡。(但是有欧皇这样过了)
一开始想写分治,也可惜我太菜了没写出来。
然后桶排偷鸡过了(数据太弱没测出来,按道理应该会卡的。基排也可以
之后知道了这么好用的一函数:nth_element作用为求第n大的元素,并把它放在第n位置上,下标是从0开始计数的,也就是说求第0小的元素就是最小的数。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
const ll maxn=1e7;
inline ll read() {
ll s = 0, w = 1;
char ch = getchar();
while (ch < 48 || ch > 57) {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
int a[maxn];
int main() {
ll T = read();
while ( T-- ) {
ll n = read(), k = read();
for(int i=0; i<n; ++i) a[i] = read();
nth_element( a + 1, a + k, a + n + 1 );
cout<<a[k]<<endl;
}
return(0);
}B 不平行的直线
用set来存斜率。
如果斜率不存在,随便用个max来记录。
最后输出set中元素个数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
const double maxn=1e7;
inline ll read() {
ll s = 0, w = 1;
char ch = getchar();
while (ch < 48 || ch > 57) {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
set<double>s;
int x[205],y[205];
int main() {
ll n = read();
ll x[205], y[205];
for (int i = 0; i < n; ++i) x[i] = read(), y[i] = read();
for (int i = 0; i < n - 1; ++i)
for (int j = i + 1; j < n; ++j)
if (x[i] == x[j])
s.insert(maxn);
else
s.insert(double((y[i] - y[j])) / (x[i] - x[j]));
cout<<s.size()<<endl;
return 0;
}C 丢手绢
前缀和 尺取
这样就知道了每一个点的顺时针距离,然后对每个点搜索找到最大距离
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
const ll maxn=1e7;
inline ll read() {
ll s = 0, w = 1;
char ch = getchar();
while (ch < 48 || ch > 57) {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
int a[100005];
int main() {
ll n=read(),max=0;
for(int i=1;i<=n;++i)
a[i]=read(),a[i]+=a[i-1];
for(int i=0;i<n;++i){
for(int j=i;j<n;++j){
int tmp=a[j]-a[i];
if(a[j]-a[i]==a[n]/2) {
printf("%d\n",a[n]/2);
return 0;
}
else if((a[j]-a[i])>(a[n]/2) && (a[n]-a[j]+a[i])>max) max=a[n]-a[j]+a[i];
else if((a[j]-a[i])<(a[n]/2) && (a[j]-a[i])>max) max=a[j]-a[i];
}
}
printf("%d\n",max);
}D 二分
参考了大佬代码
枚举所有数判断最多的符合条件的
离散+差分
map来存数据
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
const ll maxn=1e7;
inline ll read() {
ll s = 0, w = 1;
char ch = getchar();
while (ch < 48 || ch > 57) {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
const int inf=INT_MAX;
map<int,int>a;
int main() {
ll n=read();
char c;
int tmp;
for(int i=0; i<n; ++i) {
cin>>tmp>>c;
if(c=='.') a[tmp]++,a[tmp+1]--;
else if(c=='+') a[tmp]--,a[-inf]++;
else if(c=='-') a[inf]--,a[tmp+1]++;
}
int ans=-inf;
tmp=0;
for(map<int,int>::iterator it=a.begin();it!=a.end();++it) {
tmp+=it->second;
ans=max(tmp,ans);
}
cout<<ans;
}E 交换
参考了大佬代码
题意大概可理解为有一无序数组,将其两两交换变成有序的,问最少的交换次数。
于是可以将数组以有序的形式存到另一个数组中
将每个无序数与其对应的位置相连
大概可理解为 3 1 2
↓ ↓ ↓
1 2 3
这样就有 3->2->1->3的回路,回路中形成有序的最少交换次数为2
即计算回路的个数再减即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
const ll maxn=1e7;
inline ll read() {
ll s = 0, w = 1;
char ch = getchar();
while (ch < 48 || ch > 57) {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
int a[100005],b[100005];
bool v[100005];
int main() {
ll n=read();
for(int i=1;i<=n;++i) b[i]=a[i]=read();
sort(b+1,b+n+1);
for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+n,a[i])-b;
ll ans=0;
for(int i=1;i<=n;++i)
if(!v[i]){
int tmp=i;
while(!v[tmp]) v[tmp]=1,tmp=a[tmp];
ans++;
}
printf("%d\n",n-ans);
return 0;
}
查看9道真题和解析
vivo公司氛围 351人发布