使用归并排序实现。
线段树还不会。
POJ 1804 裸题
#include <stdio.h>
#include <stdlib.h>
int num[1001];
int count;
void merge(int left, int mid, int right)
{
int temp[1001];
int i = left, j = mid + 1, k = left;
while (i <= mid&&j <= right)
{
if (num[i] > num[j])
{
count = count + mid - i + 1;
temp[k++] = num[j++];
}
else
temp[k++] = num[i++];
}
while (i <= mid) temp[k++] = num[i++];
while (j <= right) temp[k++] = num[j++];
for (i = left; i <= right; i++)
num[i] = temp[i];
}
void mergeSort(int left, int right)
{
if (left < right)
{
int mid = (left + right) / 2;
mergeSort(left, mid);
mergeSort(mid + 1, right);
merge(left, mid, right);
}
}
int main()
{
int n, i;
scanf("%d", &n);
int m, j;
for (i = 1; i <= n; i++)
{
scanf("%d", &m);
for (j = 1; j <= m; j++)
scanf("%d", &num[j]);
count = 0;
mergeSort(1, m);
printf("Scenario #%d:\n", i);
printf("%d\n\n", count);
}
return 0;
}
上交OJ 1219 变形题
用到了c++的二分函数。感觉STL还是强。但是有的学校不允许使用。这道题调了很长时间。
注意最后的结果用int会溢出,导致错误。
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
int num[200001];
long long cnt;
void merge(int left, int mid, int right)
{
int temp[200001];
int i = left, j = mid + 1, k = left;
while (i <= mid&&j <= right)
{
if (num[i] > num[j])
{
/* tle
int t;
for (t = i; t <= mid; t++)
{
if (num[t] > (2 * num[j]))
cnt++;
}*/
// 下面两行代码是关键
int pos = upper_bound(num + i, num + (mid + 1), 2 * num[j]) - num;
cnt += mid - pos + 1;
temp[k++] = num[j++];
}
else
temp[k++] = num[i++];
}
while (i <= mid) temp[k++] = num[i++];
while (j <= right) temp[k++] = num[j++];
for (i = left; i <= right; i++)
num[i] = temp[i];
}
void mergeSort(int left, int right)
{
if (left < right)
{
int mid = (left + right) / 2;
mergeSort(left, mid);
mergeSort(mid + 1, right);
merge(left, mid, right);
}
}
int main()
{
int m, j;
while (EOF != scanf("%d", &m))
{
for (j = 1; j <= m; j++)
scanf("%d", &num[j]);
cnt = 0;
mergeSort(1, m);
printf("%lld\n", cnt);
}
return 0;
}