吉首大学练习题之一:
7-33 有手就...(我手呢?) (300 分)
给定一个正整数N,第二、三行每行有N个整数。 对于第三行的每一个数,输出它在第二行数中,小于它的数的种数。
输入格式:
第一行一个正整数N(1<=N<=200000) 第二行N个32位int范围内的整数 第三行N个32位int范围内的整数
输出格式:
一行N个整数,表示对于第三行中的每个数,在第二行的数中小于它的数的种数。
输入样例:
4
1 4 2 2
1 2 3 4
结尾无空行
输出样例:
(样例解释:在[1,4,2,2]中,小于1的数有0种,小于2的数只有[1]这一种,小于3的数有[1,2,2]共两种数,小于4的数有[1,2,2]共两种)
0 1 2 2
结尾无空行
#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
int a[200010],b[200010],c[200010];
int ans = 0;
int cnt = 1;
int check(int number,int l,int r) {
while (l <= r){
int mid = (l+r)/2;
if (c[mid] > number){
r = mid-1;
}
if (c[mid] < number){
if (mid == cnt){
ans = cnt ;
break ;
} else if (c[mid+1] >= number){
ans = mid;
break;
} else {
l = mid+1;
}
}
if (c[mid] == number){
ans = mid - 1;
break;
}
}
return ans;
}
int main() {
int n;
scanf("%d",&n);
for (int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
int sum=a[1];
c[1] = a[1];
for (int i=1; i<=n; i++) {
if (a[i] != sum) {
sum = a[i];
cnt++;
c[cnt] = a[i];
}
}
for (int i=1; i<=n; i++) {
scanf("%d",&b[i]);
}
for (int i=1; i<=n; i++) {
ans = 0;
ans = check(b[i],1,cnt);
printf("%d",ans);
if(i != n)
printf(" ");
}
return 0;
}
咋说呢,,自己一开始题目意思理解错了,,导致心态炸裂。写了两天remake了7次,好在第八次想通了,搞定了,主要用到的算法是二分查找加快排,由于c++快排比较作弊,就用了c++,还是比较好用的,
下面附上c 的快排模板
void quick_sort(int a[],int l,int r) {
int i=l, j=r, value=a[i];
if (l <= r){
while (i < j){
while (i < j && a[j] >= value){
j--;
}
if (i < j){
a[i++] = a[j];
}
while (i < j && a[i] <= value){
i++;
}
if (i < j){
a[j--]=a[i];
}
}
a[i] = value;
quick_sort(a,l,i-1);
quick_sort(a,i+1,r);
}
}
主要思路是先排序,再去重,最后二分查找一下就好了。