2

Given an array of n integers, indexed from 1->n. The task is to perform of Q given queries, and print the sum of the array after each queries.

We can perform three types of operations:

  • 1 X: add X to the array (its index will be n+1, n+2,...)
  • 2 Y: remove element with index Y from the array
  • 3 Z: for each element i in the array, perform i^Z (i xor Z)

Example:

Input

arr[] = {2, 3, 9, 5, 6, 6}, Q = 5
1 3
3 5
2 2
3 2
2 7

Output: 34 37 31 27 23

Explanation:

1 3 -> arr[] = {2, 3, 9, 5, 6, 6, 3} -> sum = 34

3 5 -> arr[] = {7, 6, 12, 0, 3, 3, 6} -> sum = 37

2 2 -> arr[] = {7, 12, 0, 3, 3, 6} -> sum = 31

3 2 -> arr[] = {5, 14, 2, 1, 1, 4} -> sum = 27

2 7 -> arr[] = {5, 14, 2, 1, 1} -> sum = 23

P/S: I'm trying to solve the problem with Segment Tree, but I can't update the tree with XOR operator. Is there any other way to solve this problem? I'm trying to solve it in O(n.logn)

unglinh279
  • 675
  • 4
  • 24
  • How does `2 7` (the last query) work? It seems to be removing the 6th element of the array (not the 7th). Or rather, my question I suppose is this: does the remove operation shrink the array or is there a "hole" in the array after the operation? – Maurycyt Aug 12 '21 at 15:45
  • 1
    Not sure why you need a tree. Hint: try to calculate each bit of the sum separately. – n. m. could be an AI Aug 12 '21 at 16:07
  • @Maurycyt that's what i'm also struggling with, the "2 7" query remove the element with index 7 (not the 7th element) which is the 6th element because we removed the element with index 2 – unglinh279 Aug 12 '21 at 16:11
  • @Maurycyt yes we might have to leave a "hole" where the element is deleted so the index can work correctly – unglinh279 Aug 12 '21 at 16:12
  • @n.1.8e9-where's-my-sharem. correct me if im wrong, but wouldn't it make the time complexity O(n^2)? – unglinh279 Aug 12 '21 at 16:15
  • 1
    No, considering every bit separately will only increase the constant, as there are (most likely) at most 64 bits to consider – Maurycyt Aug 12 '21 at 16:16
  • 1
    You don't need to go over each number every time you execute a query. You only need to do it once, and store the results. Then you can update these results very quickly. – n. m. could be an AI Aug 12 '21 at 16:19

2 Answers2

5

Assuming your numbers do not exceed some standard constant like 232 or 264, we can do this in constant time, by counting the bits separately.

You will need to:

  1. Remember how many numbers there are in the array
  2. Remember how many lit bits there are at every position in the binary positioning system.

So here's your example, expanded into bits, with the least significant ones at the top:

2  3  9  5  6  6  3 | sum
-------------------------
0  1  1  1  0  0  1 | 4
1  1  0  0  1  1  1 | 5
0  0  0  1  1  1  0 | 3
0  0  1  0  0  0  0 | 1

Now, that means that there are

  • 4 "first" bits lit
  • 5 "second" bits lit
  • 3 "third" bits lit and
  • 1 "fourth" bit lit.
  • The number of numbers is 7.
  • The sum of these numbers is 34

We now xor this with 5, which is 0101 in binary, so there will now be

  • 7 - 4 = 3 "first" bits lit
  • 5 "second" bits lit
  • 7 - 3 = 4 "third" bits lit
  • 1 "fourth" bit lit

If we sum this up, we get 3 * 2^0 + 5 * 2^1 + 4 * 2^2 + 1 * 2^3 = 37 (where now by ^ I mean exponentiation as opposed to xor).

So this is what you do every time the xor operation pops up. Adding and removing numbers is the easy parts because you go over their bits and accordingly adjust the counts of lit "i-th" bits in the array.

Maurycyt
  • 676
  • 3
  • 19
2

Thanks to Maurycyt I have solved the problem. Below is my code in case anyone need it

const int MAX = 1e5 + 5;
const int MAXBIT = 32;
int n, q, num, xor_add;
int arr[MAX], sum[32];

int getSum()
{
    int res = 0;
    for(int i = 0; i < MAXBIT; i++)
        res += sum[i]*(1<<i);
    return res;
}

void updateXor(int x){
    xor_add ^= x;
    for(int i = 0; i < MAXBIT; i++)
        if(x & (1<<i))sum[i] = num - sum[i];
}

void add(int x){
    ++num;
    arr[n++] = x;
    for(int i = 0; i < MAXBIT; i++)
        if(x & (1<<i))sum[i]++;
}

void remv(int i){
    --num;
    int x = arr[i-1]^xor_add;
    for(int i = 0; i < MAXBIT; i++)
        if(x & (1<<i))sum[i]--;
}

int main()
{
    cin >> n >> q;
    num = n;
    for(int i = 0; i < n; i++)cin >> arr[i];

    for(int i = 0; i < MAXBIT; i++)
        for(int j = 0; j < n; j++)
            if(arr[j] & (1<<i))sum[i]++;

    while(q--){
        int id, x;
        cin >> id >> x;

        if(id == 1)add(x);
        else if(id == 2)remv(x);
        else updateXor(x);

        cout << getSum() << '\n';
    }
    return 0;
}
unglinh279
  • 675
  • 4
  • 24