逆序對問題
簡介:先對字符串做一個部分翻轉,求得翻轉結果裏逆序串的個數(兩個數字之前前面數字比後邊大,組成一個逆序串,如3,2,1中,3,1;2,1,分別是兩個逆序串)。
用例:
第一行n:2 //表示目標數據個數爲2^n個
第二行:2 1 4 3//表示這個長度爲4的數據串的各個值
第三行:4 //做4次變換
第四行:1 2 0 2 //每次的變換空間大小
輸出:
0 //輸入2,1,4,3,以2^1爲步長,變換爲1,2,3,4,完全順序排列逆序對個數爲0。
6//輸入1,2,3,4 以2^2爲步長,變換爲4,3,2,1,完全順序排列逆序對個數爲6。
6//輸入4,3,2,1 以2^0爲步長,變換爲4,3,2,1,完全順序排列逆序對個數爲6。
0//輸入4,3,2,1 以2^2爲步長,變換爲1,2,3,4,完全順序排列逆序對個數爲6。
輸入:
2
2 1 4 3
4
1 2 0 2
輸出:
0
6
6
0
思路也比較簡潔,畢竟筆試沒太多時間想精巧方法。
第一步先翻轉,用到了一個抑或交換兩數的技巧
第二步計數逆序對,我感覺這塊自己做的不太好,也因爲這裏超時了,只過了50%用例。有興趣的朋友可以給提點改進意見,但是整理來說比較容易看懂。
#include<iostream>
using namespace std;
void reverse(int targetSize, int * target, int step) {
if (step == 1)
return;
for (int i = 0; i < targetSize; i+= step)
{
for (int j = 0; j < step; j += 2)
{
//target[i+j]與target[i+step-1-j]交換
target[i + j] = target[i+j]^target[i+step-1-j];
target[i+step-1-j] =target[i+j]^target[i+step-1-j];
target[i + j] = target[i + j]^target[i+step-1-j];
}
}
int countNXD(int dataSize,int *data) {
int ret=0;
for (int i = 0; i < dataSize-1; i++)
{
for (int j = i+1; j < dataSize; j++) {
if (data[i] > data[j])
ret++;
}
}
return ret;
}
int main() {
int n;
cin >> n;
if (n == 0)
{
cout << 0;
return 0;
}
int dataSize = pow(2,n);
int * data= new int [dataSize];
for (int i = 0; i < dataSize; i++) {
cin >> data[i];
}
int m;
cin >> m;
int *test = new int[m];
for (int i = 0; i < m; i++)
{
cin >> test[i];
}
for (int i = 0; i < m; i++)
{
int ret;
reverse(dataSize,data, pow(2,test[i]));
ret=countNXD(dataSize,data);
cout << ret<<endl;
}
delete[]data;
delete[]test;
return 0;
}