0

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];

これは問題なく動作しますが、プログラムの速度を上げようとしています。同じ操作を実行するより良い方法はありますか?

4

2 に答える 2

3

ビットセットの使用を検討してください。パフォーマンスを比較してください - 多分それは良くなるでしょう。

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();

さらに最適化するには(測定してください、信じないでください)、独自のバージョンのビットセットを使用できます<>、これはテストされていないコードです:

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
于 2012-09-14T21:31:34.250 に答える
1

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 ビット整数で試すことです。個人的には、数ビットしか反転しない場合を除いて、このアプローチは他の何よりも高速であると考えています。

右側のマスクに 1 ビットずつずれているエラーがある可能性があります。誰かがそれを見つけたら、コメントしてください。脳が空っぽ。=)

于 2012-09-14T22:20:04.693 に答える