### SPyofgame's blog

By SPyofgame, history, 3 months ago,

I come to a fun problem, and after I tried hard to solve it, I curiously to find better algorithm, but I cant.

### The problem is:

There are $N$ buildings with $a_1, a_2, \dots, a_n$ metters height. These days are hard, the heavy raining weather still not ended yet. In day $d$, every building with height $h$ only have $x_d = \lfloor \frac{h}{d} \rfloor$ height left of good space to use, while others are sunk underwater. Every building having the same value $x_d$ on day $d$ will group together (including $x_d = 0$ which sunk completely underwater) in a way that no other building with same value $x_d$ in another group.

### The question is:

Output $N$ lines, in each size $s$ from $1$ to $n$, what is the earliest day $d$ that have at least one group of size $s$ (if there is no suitable day then output -1)

### The constraints are:

• Subtaks 1: $n \leq 100~ and ~a_i \leq 2.10^5$
• Subtaks 2: $n \leq 300~ and ~a_i \leq 3.10^6$
• Subtaks 3: $n \leq 300~ and ~a_i \leq 5.10^7$

### The examples are:

Example 1

Input:

3
1 2 5


Output:

1
3
6


Explanation:

Day 1: $x[d] =$ { $\lfloor \frac{1}{1} \rfloor, \lfloor \frac{2}{1} \rfloor, \lfloor \frac{5}{1} \rfloor$ } $=$ { $1, 2, 5$ } — First group of size 1: Any of {$1$} {$2$} {$5$}

Day 2: $x[d] =$ { $\lfloor \frac{1}{2} \rfloor, \lfloor \frac{2}{2} \rfloor, \lfloor \frac{5}{2} \rfloor$ } $=$ { $0, 1, 2$ }

Day 3: $x[d] =$ { $\lfloor \frac{1}{3} \rfloor, \lfloor \frac{2}{3} \rfloor, \lfloor \frac{5}{3} \rfloor$ } $=$ { $0, 0, 1$ } — First group of size 2: Only {$1, 2$}

Day 4: $x[d] =$ { $\lfloor \frac{1}{4} \rfloor, \lfloor \frac{2}{4} \rfloor, \lfloor \frac{5}{4} \rfloor$ } $=$ { $0, 0, 1$ }

Day 5: $x[d] =$ { $\lfloor \frac{1}{5} \rfloor, \lfloor \frac{2}{5} \rfloor, \lfloor \frac{5}{5} \rfloor$ } $=$ { $0, 0, 1$ }

Day 6: $x[d] =$ { $\lfloor \frac{1}{6} \rfloor, \lfloor \frac{2}{6} \rfloor, \lfloor \frac{5}{6} \rfloor$ } $=$ { $0, 0, 0$ } — First group of size 3: Only {$1, 2, 5$}

Example 2

Input:

3
1 1 5


Output:

1
1
6


Explanation:

Day 1: $x[d] =$ { $\lfloor \frac{1}{1} \rfloor, \lfloor \frac{1}{1} \rfloor, \lfloor \frac{5}{1} \rfloor$ } $=$ { $1, 1, 5$ } — First group of size 1: Any of {$1$} {$1$} {$5$}

Day 2: $x[d] =$ { $\lfloor \frac{1}{2} \rfloor, \lfloor \frac{1}{2} \rfloor, \lfloor \frac{5}{2} \rfloor$ } $=$ { $0, 0, 2$ } — First group of size 2: Only {$1, 1$}

Day 3: $x[d] =$ { $\lfloor \frac{1}{3} \rfloor, \lfloor \frac{1}{3} \rfloor, \lfloor \frac{5}{3} \rfloor$ } $=$ { $0, 0, 1$ }

Day 4: $x[d] =$ { $\lfloor \frac{1}{4} \rfloor, \lfloor \frac{1}{4} \rfloor, \lfloor \frac{5}{4} \rfloor$ } $=$ { $0, 0, 1$ }

Day 5: $x[d] =$ { $\lfloor \frac{1}{5} \rfloor, \lfloor \frac{1}{5} \rfloor, \lfloor \frac{5}{5} \rfloor$ } $=$ { $0, 0, 1$ }

Day 6: $x[d] =$ { $\lfloor \frac{1}{6} \rfloor, \lfloor \frac{1}{6} \rfloor, \lfloor \frac{5}{6} \rfloor$ } $=$ { $0, 0, 0$ } — First group of size 3: Only {$1, 2, 5$}

Example 3

Input:

3
2 2 2


Output:

-1
-1
2


Explanation:

Day 1: $x[d] =$ { $\lfloor \frac{2}{1} \rfloor, \lfloor \frac{2}{1} \rfloor, \lfloor \frac{2}{1} \rfloor$ } $=$ { $2, 2, 2$ } — First group of size 3: Only {$2, 2, 2$}

Day 2: $x[d] =$ { $\lfloor \frac{2}{2} \rfloor, \lfloor \frac{2}{2} \rfloor, \lfloor \frac{2}{2} \rfloor$ } $=$ { $0, 0, 0$ }

Day 3: $x[d] =$ { $\lfloor \frac{2}{3} \rfloor, \lfloor \frac{2}{3} \rfloor, \lfloor \frac{2}{3} \rfloor$ } $=$ { $0, 0, 0$ }

Day 3 $\leq k \rightarrow \infty$: $x[d] =$ { $\lfloor \frac{2}{k} \rfloor, \lfloor \frac{2}{k} \rfloor, \lfloor \frac{2}{k} \rfloor$ } $=$ { $0, 0, 0$ } — There are no group of size 1 and 2

### My approach to this problem:

Observation: Harmonic Sequence

We consider this Harmonic Sequence: $S =$ {$\lfloor \frac{n}{x} \rfloor\ |\ x = 1\dots n$} = {$\lfloor \frac{n}{1} \rfloor, \lfloor \frac{n}{2} \rfloor, \lfloor \frac{n}{3} \rfloor, \dots , \lfloor \frac{n}{n - 1} \rfloor , \lfloor \frac{n}{n} \rfloor$}

And lets $L$ is Unique Harmonic Sequence. $L =$ {$x\ |\ x \in S$} or/and ($\forall (i \neq j) \in L \rightarrow L_i \neq L_j$) (I will use the set $L$ beneath)

Then the number of unique element in array is atmost $2 \sqrt{N}$. Hence $|L| \leq 2 \sqrt{N}$

Subtask 1: A[i] <= 2 * 10^5

Since day $k > max(a[i])$ will make all array always being as $x[k] =$ {$0, 0, \dots, 0$}, we only need to check for each value $k \in [1, d]$. Then we can calculate how many group of size $s$ in day $k$. My approach is to increase the value $f[\lfloor \frac{a_i}{k} \rfloor] = s$ means in day $\lfloor \frac{a_i}{k} \rfloor$ have group of size $s$, then minimize the first day we have the group of size $s$

This approach is $O(n \times max(a_i))$

int main()
{
int n;
cin >> n;

vector<int> a(n);
for (int &x : a) cin >> x;
int k = *max_element(all(a)) + 1;

vector<int> f(k + 1, 0);
vector<int> q(n + 1, +INF);
for (int x = 1; x <= k; ++x) /// Checking possible dividing value
{
for (int t : a) ++f[t / x];               /// Calculating value f[] for each day [t / x]
for (int t : a) minimize(q[f[t / x]], x); /// Minimize first day have group of size k
for (int t : a) --f[t / x];               /// Reset the array
}

for (int i = 1; i <= n; ++i)
cout << (q[i] == +INF ? -1 : q[i]) << '\n';

return 0;
}

Subtask 2: A[i] <= 3 * 10^6

Lets $setL$ be a set of good potential $k$ for dividing. Since there are some $k$ that having group of size $s$ but never will be good enough to be the smallest day. That is for each $a_i$, we find all $k$ that have smallest day $d$ that might appear a group of size $\lfloor \frac{a_i}{k} \rfloor$ and insert into $setL$.

The upper bound complexity is $O(n\ \times k\ log(k))$ where $k = |setL| = O(n \times \sqrt{max(a_i)})$ but since $a_i$ is small, and the bigger $n$ is, the more number of duplicate values will all be eliminated by using $set<>$. It would reduce both complexity and constant factor significantly.

int main()
{
int n;
cin >> n;

set<int> setL;
vector<int> a(n);
for (int &x : a)
{
cin >> x;

int sqrtx = sqrt(x);
for (int t = 1; t <= sqrt(x); ++t)
{
setL.insert(x / t + 1);
setL.insert(t + 1);
}
setL.insert(x + 1);
setL.insert(1);
}

vector<int> res(n + 1, +INF);
for (int x : setL)
{
map<int, int> F;
for (int t : a) ++F[t / x];                 /// Calculating value f[] for each day [t / x]
for (int t : a) minimize(res[F[t / x]], x); /// Minimize first day have group of size k
}

for (int g = 1; g <= n; ++g) cout << (res[g] == +INF ? -1 : res[g]) << '\n';
return 0;
}

Subtask 3: A[i] <= 5 * 10^7

With $T = \sqrt{max(a_i)}$ then all such $k \leq T$ are potential. We only care for such $k > T$ which we can use branch and bound to reduce constant matter.

By using map, we can calculate faster by ignoring duplicates. Iterating through map reducing the $O(log)$ factor each query.

Since we solve each potential $k$ from large to smaller, the value $cur$ will be from small to larger, so we dont have to use $min(a, b)$ function, and only update for each $res[x]$ once. We exit when all $N$ query are found or we tried all potential $k$

Hence, the complexity is $O(n\ log\ n + n \times (k + \sqrt{max(a_i)}) + k\ log\ k)$ where $k = |setL|$

int n;
int cnt = 0;
vector<int> a;
map<int, int> b;
map<int, int>::iterator it;
vector<int> res;

void out()
{
for (int i = 1; i <= n; ++i) cout << (res[i] == +INF ? -1 : res[i]) << '\n';
exit(0);
}
void solve(int x)
{
int sum = 0, val = -1;
for (it = b.begin(); it != b.end(); ++it)
{
int cur = it->first / x;
if (cur != val)
{
val = cur;
if (sum && res[sum] == +INF) { res[sum] = x; if (++cnt == n) out(); }
sum = 0;
}
sum += it->second;
}
if (sum && res[sum] == +INF) { res[sum] = x; if (++cnt == n) out(); }
}

int main()
{
cin >> n;
a.resize(n);
for (int &x : a)
{
cin >> x;
++b[x];
}

res.assign(n + 1, +INF);
int k = ceil(sqrt(*max_element(all(a))));
for (int x = 1; x <= k; ++x) solve(x);

if (k > 1)
{
set<int> setL;
for (it = b.begin(); it != b.end(); ++it)
{
int x = it->first;
int lim = min(k, x / (k - 1));
for (int t = 1; t <= lim; ++t)
{
int v = x / t + 1;
setL.insert(v);
}
}
for (int x : setL) solve(x);
}
out();
return 0;
}


### My question

• Is there a better algorithm for larger $N$ ? (upto $10^4, 10^6$)

• Is there a better algorithm for larger $a_i$ ? (upto $10^{12}, 10^{16}, 10^{18}$)

• Can I use combinatorics or euclidian algorithm for this problem ?

• +18

 » 2 months ago, # |   -28 This is proof that ratism is real !
 » 2 months ago, # |   +28 Always provide a source. It's so scary nowadays to answer any blog, especially during Codechef Long. People keep asking about problems from ongoing contests -_-
•  » » 2 months ago, # ^ |   +16 Ad here's maybe not that common opinion: beginners only waste time by modifying problems or trying to solve them for big constraints. There are thousands of problems out there that are for sure solvable.
•  » » » 2 months ago, # ^ | ← Rev. 3 →   0 :< I kept your advice from the last time but sometimes I found some interesting problems yet learning something new when solved it with a higher level & variant of the problems. About the problemI solved this problem in two days with hours of observation, submission attempting and finally optimized enough to get this problem Accepted. When I asked my teacher he told me that my approach is the same as the solution but there is maybe a way of using some Combinatorics or Euclidean to solve it more effecient that I think worth to learn it or try harder. Which in some problems I dont find it wasting my time but also learn something new and tricks. And learning from your advice, not for every problems I pass I try to do so like a year ago. 
•  » » 2 months ago, # ^ | ← Rev. 2 →   0 Yes sir but it is not possible to do so in this case that I am unable to give the source since it is from a private ongoing training contest whose class is over yet and my teacher move to somewhere out to teach but there is still the problem. And I am asking for permission to public the problem
•  » » 2 months ago, # ^ | ← Rev. 2 →   0 Here is the source. The author allowed me to clone to a new problem and also wondering whether there is a better solution too ^^. I have also write both Vietnamese/English version of statements
 » 2 months ago, # |   0 Auto comment: topic has been updated by SPyofgame (previous revision, new revision, compare).