我想对 bool 数组的连续元素块执行 not 操作,然后读回完整的数组。我正在使用以下代码来执行操作。
bool arr[100000]={0};
cin>>x>>y;
for(i=x; i<=y; i++)
arr[i]=!arr[i];
//Some other operations on the array
for(i=0; i<=100000; i++)
arr+=arr[i];
这工作正常,但我正在尝试提高程序的速度。有没有更好的方法来执行相同的操作?
我想对 bool 数组的连续元素块执行 not 操作,然后读回完整的数组。我正在使用以下代码来执行操作。
bool arr[100000]={0};
cin>>x>>y;
for(i=x; i<=y; i++)
arr[i]=!arr[i];
//Some other operations on the array
for(i=0; i<=100000; i++)
arr+=arr[i];
这工作正常,但我正在尝试提高程序的速度。有没有更好的方法来执行相同的操作?
考虑使用位集。比较性能-也许会更好。
std::bitset<100000> arr;
cin>>x>>y;
for(i=x; i<=y; i++)
arr.flip(i);
//Some other operations on the array
unsigned int carr = arr.count();
为了更优化(请测量并且不要相信),您可以使用您自己的 bitset<> 版本,这不是测试代码:
const size_t arr_bitlen = 100000;
typedef unsigned int arr_type;
const size_t arr_type_size = sizeof(arr_type);
const size_T arr_len = (arr_bitlen + arr_type_size - 1) / arr_type_size;
arr_type arr[arr_len] = { 0 };
cin>>x>>y;
unsigned int x_addr = x / arr_type_size;
unsigned int y_addr = y / arr_type_size;
unsigned int x_bit = x % arr_type_size;
unsigned int y_bit = y % arr_type_size;
if (0 == x_bit)
for (i=x_addr; i<=y_addr; i++)
arr[i] = ~arr[i]; // revert all bits (bools)
else {
// deal with first element in range ( ....xxxx - change only x-s
arr_type x_mask = ((1 << x_bit) - 1) << (arr_type_len - x_bit);
arr[x_addr] ^= x_mask;
for (i = x_bit + 1; i < arr_type_size; ++i)
arr[i] = ~arr[i]; // revert all bits (bools)
}
if (y_bit > 0) // try to invert 0..y_bit in arr[y_addr + 1] by yourself
//Some other operations on the array
see implementation of std::bitset<N>::count() - it is very clever - just copy it
既然我发表了关于使用 int(或者实际上是 int64)的评论,我不妨把它写下来,你可以评估它是否值得。会是这样的。请原谅任何错误,因为我只是在我的孩子们正在观看可笑的垃圾周六早上卡通片时将其放入浏览器中。
// I'm gonna assume 32-bit ints here. Makes the other maths clearer.
// Sorry about all the '4' and '32' constants =P
const size_t arrLen = 100000 / 4 + 1;
int arr[arrLen];
//This gets filled with your data...
memset((void*)arr, 0, arrLen*4);
cin >> x >> y;
int leftMask = 0xffffffff >> (x % 32); // "(x & 0x1f)" faster?
int rightMask = ~(0x7fffffff >> (y % 32)); // "(y & 0x1f)" faster?
x /= 32; // "x >>= 5" faster?
y /= 32; // "y >>= 5" faster?
if( x == y )
{
// Intersect the masks
leftMask &= rightMask;
arr[x] = (arr[x] & ~leftMask) | (~arr[x] & leftMask);
}
else if( x < y )
{
// Flip the left and right ends
arr[x] = (arr[x] & ~leftMask) | (~arr[x] & leftMask);
arr[y] = (arr[y] & ~rightMask) | (~arr[y] & rightMask);
// Flip everything in between
for( int i = x+1; i < y; i++ ) {
arr[i] ^= 0xffffffff; // Or arr[i] = ~arr[i] -- whichever is faster
}
}
上述循环的替代方案,如果它有任何区别......
// Flip everything in between
for( int *a = arr+x+1, *b = arr+y; a < b; a++ ) {
*a = ~*a;
}
练习是尝试使用 64 位整数。就个人而言,我认为这种方法比其他任何方法都快,除非你只翻转几位。
我的右手掩码中可能有一个位错误。如果有人发现它,请发表评论。脑袋空空的。=)