蓝桥杯C++大学B组一个月冲刺记录2024/3/5
规则:每日三题
1.归并排序
给定你一个长度为 n的整数数列。
请你使用归并排序对这个数列按照从小到大进行排序。
并将排好序的数列按顺序输出。
归并
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int M = 1e5+5;
int p[M];
int n;
void merge(int l,int mid ,int r){
vector<int>temp;
int i = l;
int j = mid + 1;
while(i <= mid&&j <= r){
if(p[i] < p[j]){
temp.push_back(p[i]);
i++;
}
else{
temp.push_back(p[j]);
j++;
}
}
while(i <= mid){
temp.push_back(p[i]);
i++;
}
while(j <= r){
temp.push_back(p[j]);
j++;
}
for(int i = 0;i < temp.size();++i) p[l+i] = temp[i];
return;
}
void merge_sort(int l,int r){
if(l < r){
int mid = (l+r)/2;
merge_sort(l , mid);
merge_sort(mid+1 , r);
merge(l, mid ,r);
}
}
int main(){
cin >> n;
for(int i = 0;i < n;++i) cin >> p[i];
merge_sort(0,n-1);
for(int i = 0;i < n;++i) cout << p[i] << ' ';
return 0;
}
2.逆序对的数量
给定一个长度为 n的整数数列,请你计算数列中的逆序对的数量。
逆序对的定义如下:对于数列的第 i个和第 j个元素,如果满足 i<j且 a[i]>a[j],则其为一个逆序对;否则不是。
归并
#include<iostream>
#include<vector>
using namespace std;
const int M = 1e5 + 5;
typedef long long LL;
int p[M];
int n;
LL merge(int l,int r){
if(l >= r) return 0;
int mid = (l+r)/2;
LL ans = merge(l,mid) + merge(mid+1,r);
vector<int>temp;
int i = l;
int j = mid+1;
while(i <= mid&&j <= r){
if(p[j] >= p[i]){
temp.push_back(p[i]);
i++;
}
else{
ans += mid - i + 1;
temp.push_back(p[j]);
j++;
}
}
while(i <= mid){
temp.push_back(p[i]);
i++;
}
while(j <= r){
temp.push_back(p[j]);
j++;
}
for(int i = 0;i < temp.size();++i) p[i+l] = temp[i];
return ans;
}
int main(){
cin >> n;
for(int i = 0;i < n;++i){
cin >> p[i];
}
cout << merge(0,n-1) << endl;
return 0;
}
3.火柴排队
涵涵有两盒火柴,每盒装有 n根火柴,每根火柴都有一个高度。
现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:
∑i=1n(ai−bi)2其中 ai表示第一列火柴中第 i个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。
请问得到这个最小的距离,最少需要交换多少次?
如果这个数字太大,请输出这个最小交换次数对 99,999,997取模的结果。
重点是把排好序的相应下标去计算逆序对
离散化+归并
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int M = 1e5+10;
const int mod = 99999997;
typedef pair<int,int>PII;
typedef long long LL;
PII a[M],b[M];
int c[M];
bool cmp(PII a, PII b){
return a.first < b.first;
}
LL merge(int l,int r){
if(l >= r) return 0;
int mid = (l + r)/2;
LL ans = merge(l , mid) + merge(mid + 1 , r);
int i = l,j = mid + 1;
vector<int>t;
while(i <= mid && j <= r){
if(c[j] >= c[i]){
t.push_back(c[i]);
i++;
}
else{
ans += mid - i + 1;
t.push_back(c[j]);
j++;
}
}
while(i <= mid){
t.push_back(c[i]);
i++;
}
while(j <= r){
t.push_back(c[j]);
j++;
}
for(int i = 0;i < t.size();++i) c[i + l] = t[i];
return ans;
}
int main(){
int n;
cin >> n;
for(int i = 0;i < n;++i){
cin >> a[i].first;
a[i].second = i;
}
for(int j = 0;j < n;++j){
cin >> b[j].first;
b[j].second = j;
}
sort(a,a + n,cmp);
sort(b,b + n,cmp);
for(int i = 0;i < n;++i){
c[b[i].second] = a[i].second;
}
cout << merge(0,n-1)%mod << endl;
return 0;
}