逆序对问题
简介:先对字符串做一个部分翻转,求得翻转结果里逆序串的个数(两个数字之前前面数字比后边大,组成一个逆序串,如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;
}