poj 2299 1804 2085 求逆序对

关于逆序对的总结:

poj 2299 输入一个字串求逆序对个数: 

思路:

主要是利用归并排序,中间加入计数器,就可以了,注意使用scanf ,printf 减少输入输出时间,结果用__int64保存。

 

poj 1804 求逆序对个数(同poj 2299)

 

#include <iostream> using namespace std; int a[500001]; int b[500001]; int n; __int64 res; void copy(int *a, int *b, int l, int r) { for (int i = l; i <= r; ++i) a[i] = b[i]; } void merge(int *a, int l, int mid, int r) { int i = l; int j = mid + 1; while (i <= mid && j <= r) { if (a[i] <= a[j]) b[l++] = a[i++]; else { b[l++] = a[j++]; res += mid - i + 1;//因为这里左、右半部分是排序好的,所以a[i]往后的数值全都大于a[j] //所以直接加上后面那么多就行了。 } } while (i <= mid) b[l++] = a[i++]; while (j <= r) b[l++] = a[j++]; } void mergesort(int *a, int l, int r) { if (l < r) { int mid = (l+r)/2; mergesort(a,l,mid); mergesort(a,mid+1,r); merge(a,l,mid,r); copy(a,b,l,r); } } int main() { while (cin>>n) { if (n == 0) break; for (int i = 0; i < n; ++i) cin>>a[i]; res = 0; mergesort(a, 0, n-1); printf("%I64d/n", res); } return 0; }

 

poj 1085 给出长度n 和逆序对个数,求最小的序列

思路:

先求出顺序的最大数i ,顺序输出从1 到 i :

输出 逆序中的决定性数字 K: ( k = seq + i - (n - i) * (n - i - 1) / 2)

从n 逆序输出非k的 i:

 

#include <iostream> using namespace std; int main() { int n, seq, i, j; while(scanf("%d%d", &n, &seq) && (n + seq) != -2) { int total = 0; for(i = n; i >= 1; i--) { total += n - i; if(total >= seq) break; } for(j = 1; j < i; j++) printf("%d ", j); int k = seq + i - (n - i) * (n - i - 1) / 2; printf("%d ", k); for(j = n; j >= i; j--) if(j != k) printf("%d ", j); printf("/n"); } return 0; }  

 

你可能感兴趣的:(iostream,merge)