Description
.人比人,气死人;鱼比鱼,难死鱼。小鱼最近参加了一个“比可爱”比赛,比的是每只鱼的可爱程度。参赛的鱼被从左到右排成一排,头都朝向左边,然后每只鱼会得到一个整数数值,表示这只鱼的可爱程度,很显然整数越大,表示这只鱼越可爱,而且任意两只鱼的可爱程度可能一样。由于所有的鱼头都朝向左边,所以每只鱼只能看见在它左边的鱼的可爱程度,它们心里都在计算,在自己的眼力范围内有多少只鱼不如自己可爱呢。请你帮这些可爱但是鱼脑不够用的小鱼们计算一下。
Input
第一行输入一个整数n,表示鱼的数目。
第二行内输入n个整数,用空格间隔,依次表示从左到右每只小鱼的可爱程度。
Output
行内输出n个整数,用空格间隔,依次表示每只小鱼眼中有多少只鱼不如自己可爱。
Sample Input 1
6
4 3 0 5 1 2
Sample Output 1
0 0 0 3 1 2
Hint
1<=n<=10^6
思路
有两种解法
第一种是普通归并排序,增加一个 灵性的tt变量 储存大于左边的值。
#include<bits/stdc++.h>
using namespace std;
const int m = 1000005;
struct aa
{
int v, p;//v:value值 p:position位置
}a[m];
int ans[m];
int read() {//快读
char c = getchar();
int fu = 1;
while (c < '0' || c>'9') {
if (c == '-')
fu = -1;
else
fu = 1;
c = getchar();
}
int t = 0;
while (c >= '0' && c <= '9') {
t = (t << 3) + (t << 1) + (c ^ 48);
c = getchar();
}
return t * fu;
}
void Merge(aa a[], int lb, int le, int re)
{
int tlb = lb;
int rb = le + 1;
int mb = lb;
//lb:left begin le:left end
//rb:left begin re:right end
//mb:merge数组指针
aa t[m];
int tt = 0;//现在 左边有多少个数 比 右边当前数字小
while (mb <= re)//
{
if (rb > re)
{
for (int i = lb; i <= le; i++)
{
t[mb++] = a[i];
}
break;
}
else if(lb>le)
{
for (int i = rb; i <= re; i++)
{
ans[a[i].p] += tt;//由于左边可能因为 lb超出 而导致 右边数字未能全部遍历,要增加此语句进行补全
t[mb++] = a[i];
}
break;
}
if (a[rb].v > a[lb].v) {
tt++;//当前的左边值比右边值小
t[mb++] = a[lb++];
}
else
{
ans[a[rb].p] += tt;//加上 左边比他小的数
t[mb++] = a[rb++];
}
}
for (int i = tlb; i <= re; i++)a[i] = t[i];
}
void MergeSort(aa a[],int left,int right)
{
if (left >= right)return;
int mid = left + ((right - left)>>1);
MergeSort(a,left,mid);
MergeSort(a,mid+1, right);
Merge(a,left, mid, right);
}
int main()
{
int n = read();
for (int i = 0; i < n; i++)
{
a[i].v = read();
a[i].p = i;
}
MergeSort(a, 0, n - 1);
for (int i = 0; i < n; i++)
{
printf("%d ", ans[i]);
}
return 0;
}
第二种解法比较巧妙,归并排序时 从大到小实现 这样ans每次加 只需要加 左边的 未遍历过的(一定比他小) 就可以了
#include<bits/stdc++.h>
using namespace std;
const int m = 1000005;
struct aa
{
int v, p;
}a[m];
int ans[m];
int read() {
char c = getchar();
int fu = 1;
while (c < '0' || c>'9') {
if (c == '-')
fu = -1;
else
fu = 1;
c = getchar();
}
int t = 0;
while (c >= '0' && c <= '9') {
t = (t << 3) + (t << 1) + (c ^ 48);
c = getchar();
}
return t * fu;
}
void Merge(aa a[], int lb, int le, int re)
{
int tlb = lb;
int rb = le + 1;
int mb = lb;
aa t[m];
while (mb <= re)//
{
if (rb > re)
{
for (int i = lb; i <= le; i++)
{
t[mb++] = a[i];
}
break;
}
else if(lb>le)
{
for (int i = rb; i <= re; i++)
{
t[mb++] = a[i];
}
break;
}
if (a[lb].v < a[rb].v) {
ans[a[rb].p] += le - lb + 1;
t[mb++] = a[rb++];
}
else
{
t[mb++] = a[lb++];
}
}
for (int i = tlb; i <= re; i++)a[i] = t[i];
}
void MergeSort(aa a[],int left,int right)
{
if (left >= right)return;
int mid = left + ((right - left)>>1);
MergeSort(a,left,mid);
MergeSort(a,mid+1, right);
Merge(a,left, mid, right);
}
int main()
{
int n = read();
for (int i = 0; i < n; i++)
{
a[i].v = read();
a[i].p = i;
}
MergeSort(a, 0, n - 1);
for (int i = 0; i < n; i++)
{
printf("%d ", ans[i]);
}
return 0;
}