Atcoder Beginner Contest 366 Review

Atcoder

Finally reached mint on Atcoder. :blobthumbsup:

Solved A to E, won’t go over F and G because I haven’t upsolved them yet. The problems up to E felt easy but slightly tricky to implement overall. I solved E fairly quickly but getting 3x penalty on B was a bit painful and made me drop a lot in ranking later.

Soutions

A - Election 2

Just check if either of $T$ or $A$ is greater than or equal to $\lfloor \frac{N+1}{2} \rfloor$

B - Vertical Writing

Just do what the question asks you… except what the questions asks you to do is a bit tricky to understand and implement at first.

I converted the strings to a 2D array of characters and flipped the row and column while padding the result such that if the length of the longest string converted so far was $mx$, the current string is padded with ‘*’ up to length $mx$. Refer to the code below.

C - Balls and Bag Query

Maintain a count of each unique element, as well as the number of unique elements initialized to $0$. When an element is added, if the count was $0$, add $1$ to the number of unique elements. When an element is removed, and it causes the count to hit $0$, remove $1$ from the number of unique elments.

I used a map but you can use the fact that the range of $x$ values is small $(\le 10^6)$ and use an array instead.

D - Cuboid Sum Query

Prefix sums expanded to 3D. Except I was too lazy to actually implement it so I just used the multi-dimensional segtree template from our teamnote…

E - Manhattan Multifocal Ellipse

Notice that the Manhattan distance is the sum of difference of $x$ and $y$ coordinates. This allows us to think of them separately.

For all $x_i$ smaller than or equal to a certain $x$, the difference is $x - x_i$ and for all $x_i$ larger than a certain $x$, the difference is $x_i - x$. Thus if we sort the given $x$ coordinates and calculate the prefix sum of their values, we can query for the sum of differences of $x_i$ for any given $x$ in $\mathcal{O}(log N)$ time. The same applies for the $y$ coordinates.

Combining this with the fact that the constraints for $D$ is small, we can iterate over a large enough range of $x$ values and $y$ values to find all “possible candidates” of $x$ and $y$ separately. (That is, $x$ and $y$ values whose sum of differences of $x$, $y$ coordinates is $\le D$) Notice that we have already calculated the sum of differences.

Then, for each $x$ candidate, we can find the number of possible $y$ candidates by simply binary searching on the sum of differences. Summing up the result for each $x$ will give us the answer. (Find the number of $y$ coordinates whose sum of differences is $\le \sum^{N}_{i=1}(x-x_i)$)

Initially, I mistakenly tried binary searching for the range of possible $y$ values for each $x$. I am not sure if this is entirely wrong, but I binary searched the interval separately for positive $y$ and negative $y$ incorrectly assuming the result would be monotone.

Code (C++)

A :

int N, T, A; cin >> N >> T >> A;
if(T >= (N + 1) / 2 || A >= (N + 1) / 2) {
    cout << "Yes";
} else cout << "No";

B :

char a[105][105];
char b[105][105];
string s[105];
int def[105];

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.setf(ios::fixed); cout.precision(PRECISION);

    int N; cin >> N;
    for(int i=0; i<N; i++) {
        cin >> s[i];
        for(int k=0; k<(int)s[i].size(); k++) {
            a[i][k] = s[i][k];
        }
    }
    int mx = 0;
    for(int i=0; i<N; i++) {
        for(int k=0; k<(int)s[i].size(); k++) {
            b[k][N-i-1] = a[i][k];
        }
        mx = max(mx, (int)s[i].size());
        if(i != 0) {
            if(s[i].size() < mx) {
                int target = mx;
                // cout << i << ' ' << target << endl;
                for(int k=target-1; k>=(int)s[i].size(); k--) {
                    b[k][N-i-1] = '*';
                }
            }
        } 
    }
    for(int i=0; i<mx; i++) {
        for(int j=0; j<105; j++) {
            if(b[i][j]) cout << b[i][j];
        } 
        if(b[i][0]) cout << endl;
    }
}

C :

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.setf(ios::fixed); cout.precision(PRECISION);

    map<int, int>mp; int cnt = 0;
    int Q; cin >> Q;
    while(Q--) {
        int q; cin >> q;
        if(q  == 1) {
            int x; cin >> x;
            if(!mp[x]) {
                cnt++;
                mp[x] = 1;
            } else mp[x]++;
        } if(q == 2) {
            int x; cin >> x;
            mp[x]--;
            if(!mp[x]) cnt--;
        } if(q == 3) {
            cout <<  cnt << endl;
        }
    } 
}

D :

template <class T, int... Ns> struct BIT {
	T val = 0;
	void upd(T v) { val += v; }
	T query() { return val; }
};

template <class T, int N, int... Ns> struct BIT<T, N, Ns...> {
	BIT<T, Ns...> bit[N + 1];
	template <typename... Args> void upd(int pos, Args... args) {
		for (; pos <= N; pos += (pos & -pos)) bit[pos].upd(args...);
	}
	template <typename... Args> T sum(int r, Args... args) {
		T res = 0;
		for (; r; r -= (r & -r)) res += bit[r].query(args...);
		return res;
	}
	template <typename... Args> T query(int l, int r, Args... args) {
		return sum(r, args...) - sum(l - 1, args...);
	}
};  // BIT<int,10,10> gives a 2D BIT

BIT<ll, 100, 100, 100>seg;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.setf(ios::fixed); cout.precision(PRECISION);

    int N; cin >> N;
    for(int i=1; i<=N; i++) {
        for(int j=1; j<=N; j++) {
            for(int k=1; k<=N; k++) {
                int x; cin >> x;
                seg.upd(i, j, k, x);
            }
        }
    }
    int Q; cin >> Q;
    while(Q--) {
        int xl, xr, yl, yr, zl, zr;
        cin >> xl >> xr >> yl >> yr >> zl >> zr;
        cout << seg.query(xl, xr, yl, yr, zl, zr) << endl;
    }
}

E :

ll X[200005];
ll Y[200005];
ll preX[200005];
ll preY[200005];

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.setf(ios::fixed); cout.precision(PRECISION);

    int N; cin >> N;
    ll D; cin >> D;
    for(int i=1; i<=N; i++) {
        cin >> X[i] >> Y[i];
    } sort(X+1, X+N+1); sort(Y+1, Y+N+1);
    for(int i=1; i<=N; i++) {
        preX[i] = preX[i-1] + X[i];
        preY[i] = preY[i-1] + Y[i];
    }
    ll cnt = 0;
    vector<ll>sxes; vector<ll>syes;
    for(ll x=-2020202; x<=2020202; x++) {
        ll lx = 1, rx = N, res = N+1;
        while(lx <= rx) {
            ll mid = (lx + rx) / 2;
            if(X[mid] >= x) {
                res = mid;
                rx = mid - 1;
            } else lx = mid + 1;
        }
        ll sx = x * (res - 1) - preX[res - 1] + (preX[N] - preX[res-1] - (N - res + 1) * x);
        
        if(sx > D) continue;
        else if(sx <= D) sxes.push_back(sx);
    }
    for(ll y=-2020202; y<=2020202; y++) {
        ll lx = 1, rx = N, res = N+1;
        while(lx <= rx) {
            ll mid = (lx + rx) / 2;
            if(Y[mid] >= y) {
                res = mid;
                rx = mid - 1;
            } else lx = mid + 1;
        }
        ll sx = y * (res - 1) - preY[res - 1] + (preY[N] - preY[res-1] - (N - res + 1) * y);

        if(sx > D) continue;
        else if(sx <= D) syes.push_back(sx);
    }
    sort(all(sxes)); sort(all(syes));
    for(ll &val:sxes) {
        ll res = upper_bound(all(syes), D-val) - syes.begin();
        cnt += res;
    }
    cout << cnt;
}