Balkan OI 2015 - Happiness
Authors: Andi Qu, Benjamin Qi
Isn't it convenient how the problem statement tells us what we have to do? (Try to prove the necessary condition described in the statement yourself.)
We need a data structure that supports the following:
- Insert numbers into a multiset .
- Erase numbers from .
- Check whether there exists some number such that .
Solution 1 - Sparse Segment Tree
Since we want to handle range queries with updates, the obvious option would be to use a BIT or segment tree.
However, the numbers that we want to insert can get very large (up to ). Since we have to answer queries online, using a BIT is out of the question.
Luckily, we can simply use a sparse segment tree instead!
We still need to find a way to check whether the described above exists though.
The key observation is that if we know that
for some , then we also know that
for all . This is true because
This means that the next number we need to check is .
If we choose the numbers that we check this way, then we will only check numbers for each query (since the -th number we check is always at least ).
The complexity of this algorithm is thus .
Code
1#include "happiness.h"23struct Node {4 long long l, r, val;5 Node *lc, *rc;67 Node(long long L, long long R): l(L), r(R), val(0), lc(nullptr), rc(nullptr) {}89 void update(long long p, long long v) {10 val += v;
Solution 2 - Buckets
A smarter solution is to split the elements of into the buckets for each from 0 to . Notice how there are exactly buckets.
Why is this convenient?
Firstly, only the two least elements in each bucket could potentially be bad (since ). This narrows down the number of elements we need to check significantly.
Secondly, we can store the sum of the elements in each bucket and be able to find the prefix sums of buckets in time.
We can use multisets to store the elements in the buckets, so the complexity of this algorithm is . In practice, this solution runs faster than the first solution.
Code
1#include "happiness.h"2#include <bits/stdc++.h>34using namespace std;56using ll = long long;7multiset<ll> todo[40];8ll SUM[40];910void ad(ll x, int b) {
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!