HackerRank

1st Try: brutal-force solution failed 3 test cases with TLE

2nd Try: uint32_t bucketing - AC:

#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;

#define LEN 100032
typedef unsigned long long ULL;
unsigned ia[LEN/32] = {0};
unsigned ib[LEN/32] = {0};

void set_b(unsigned v[LEN/32], int b, int cnt)
{
    if (b)    // set 1
    {
        v[cnt/32] |= 1 << (cnt % 32);
    }
    else
    {
        unsigned mask = 0;
        mask |= 1 << (cnt % 32);
        mask = ~mask;
        v[cnt/32] &= mask;
    }
}

int get_b(unsigned v[LEN/32], int inx)
{
    int binx = inx % 32;
    int sinx = inx / 32;
    unsigned b = v[sinx] & (1 << (binx));
    return b ? 1 : 0;
}

void set_v(string &s, unsigned v[LEN/32])
{
    size_t n = s.length();
    for(int i = n - 1; i >= 0; i--)
    {
        int cnt = n - 1 - i;
        int b = s[i] - '0';
        set_b(v, b, cnt);
    }
}

int main() 
{
    int n, q; cin >> n >> q;
    string a, b;
    cin >> a;
    set_v(a, ia);
    cin >> b;
    set_v(b, ib);

    while(q--)
    {
        string cmd;
        int v0 = 0, v1 = 0;
        cin >> cmd;
        if(cmd[0] == 's')
        {
            cin >> v0 >> v1;
            if(cmd[4] == 'a')
            {
                set_b(ia, v1, v0);
            }
            if(cmd[4] == 'b')
            {
                set_b(ib, v1, v0);
            }
        }
        if(cmd[0] == 'g')
        {
            cin >> v0;
            
            int sinx = v0 / 32;
            int binx = v0 % 32;
            
            unsigned sum = ia[sinx] + ib[sinx];
            unsigned bv = sum & (1 << binx);
            if(binx > 0)
            {                
                unsigned tail = (1 << binx) - 1;
                if ((sum & tail) < tail) // no need to check prev.
                {
                    cout << (bv ? 1 : 0);
                    continue;
                }
            }

            bool bCarry = false;
            sinx --;
            while(sinx >= 0)
            {
                ULL sum = (ULL)ia[sinx] + (ULL)ib[sinx];                
                if (sum < 0xFFFFFFFF)
                {
                    bCarry = false;
                    break;
                }
                else if(sum > 0xFFFFFFFF)
                {
                    bCarry = true;
                    break;
                }
                sinx --;
            }
            //
            if (!bCarry)
                cout << (bv ? 1 : 0);
            else
                cout << (bv ? 0 : 1);
        }
    }

    return 0;
}
View Code

By checking the LeaderBoard, I learnt a beautiful SegTree solution:

class Node
{
public:
    int bit;        // 01: bits[left, right] are all 01; 
                //  -1: bits[left, right] are not same
    int left, right;   // range: bits[left, right]
};

Each node takes in charge of a range of bits, and records bits values of the range. And we updatequery bits of sum upon this SegTree.. Neat!

原文地址:https://www.cnblogs.com/tonix/p/4587515.html