3 Paradigms
3 Paradigms
Solving
Paradigms
Greedy
Algorithms
Linear Sweep
Problem-Solving Paradigms
Binary Search COMP4128 Programming Challenges
Term 3, 2022
Table of Contents 2
Problem-
Solving
Paradigms
Greedy
Algorithms
Linear Sweep
1 Greedy Algorithms
Binary Search
2 Linear Sweep
3 Binary Search
Greedy Algorithms 3
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms
Binary Search
Source Orac
Example problem: Psychological Jujitsu 7
Problem-
Solving
Paradigms
Example Input
Greedy
Algorithms 3
Linear Sweep 3 1 2
Binary Search
Example Output 4
Problem-
Solving
Paradigms
Linear Sweep
Binary Search
Problem-
Solving
Paradigms
Consider the round where the opponent plays card N.
Greedy
Algorithms
Linear Sweep In such a round, we can either draw (play card N too) or
Binary Search lose.
Problem-
Solving
Paradigms Okay, how about the play patterns where we play card N
and draw?
Greedy
Algorithms
Then it’s like we’re repeating the problem with N − 1 in
Linear Sweep
place of N.
Binary Search
Problem-
Solving
Paradigms Implementation
#include <bits/stdc ++.h>
Greedy using namespace std;
Algorithms
const int MAXN = 1005;
Linear Sweep int N, opp[MAXN ];
Binary Search
int main () {
cin >> N;
for (int i = 0; i < N; i++) cin >> opp[i];
int ans = 0;
for (int i = 1; i <= N; i++) {
// draw > i, lose round i, win rounds < i
int cur = 0;
for (int j = 0; j < N; j++) {
if (opp[j] == i) cur -= j+1;
if (opp[j] < i) cur += j+1;
}
ans = max(ans , cur);
}
cout << ans << '\n';
return 0;
}
Example problem: Psychological Jujitsu 12
Problem-
Solving
Paradigms
Linear Sweep
conditions “good” states must satisfy. For this, it helps to
Binary Search
consider a problem from different angles.
Problem-
Solving
Paradigms
Greedy
Algorithms
Linear Sweep
1 Greedy Algorithms
Binary Search
2 Linear Sweep
3 Binary Search
Linear Sweeps 14
Problem-
Solving
Paradigms
Very basic but fundamental idea. Instead of trying to do a
problem all at once, try to do it in some order that lets
Greedy
you build up state.
Algorithms
Linear Sweep
This lets you process events one by one. This can be
Binary Search easier than trying to handle them all at once.
General Principle: Having an order is better than not
having an order!
Trying to sort and pick the right order to do a problem in
is fundamental.
If there isn’t a natural order to a problem, you may as well
try to do it in any sorted order.
Even if there is a natural order, sometimes it isn’t the
right one!
Example problem: Stabbing 15
Problem-
Solving
Paradigms Problem statement You have a list of closed intervals,
each with an integer start point and end point. For
Greedy
Algorithms
reasons only known to you, you want to stab each of the
Linear Sweep intervals with a knife. To save time, you consider an
Binary Search interval stabbed if you stab any position that is contained
with the interval. What is the minimum number of stabs
necessary to stab all the intervals?
Problem-
Solving
Paradigms
Greedy Example
Algorithms
Linear Sweep
Binary Search
Problem-
Solving
Paradigms
Binary Search
Problem-
Solving
Paradigms
Greedy
Algorithms
Observation 1: We can move it so it is an end point of
Linear Sweep
an interval without decreasing the set of intervals we stab.
Binary Search
Problem-
Solving
Paradigms
Binary Search
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms Given all the intervals sorted by their end points, what do
we need to keep track of? The last stab point
Greedy
Algorithms
Is this enough? How can we be sure we haven’t missed
Linear Sweep
anything?
Binary Search
Since we always stab the next unstabbed end point, we
can guarantee that there are no unstabbed intervals that
are entirely before our last stab point.
For each next interval we encounter (iterating in ascending
order of end point), that interval can start before or
on/after our last stab point.
If it starts before our last stab point, it is already stabbed,
so we ignore it and continue.
If it starts after our last stab point, then it hasn’t been
stabbed yet, so we should do that.
Example problem: Stabbing 23
Problem-
Solving
Paradigms
Problem-
Solving Implementation
Paradigms
#include <iostream >
#include <utility >
#include <algorithm >
Greedy using namespace std;
Algorithms
const int N = 1001001;
Linear Sweep
pair <int , int > victims [N];
Binary Search
int main () {
// scan in intervals as (end , start ) so as to sort by endpoint
int n;
cin >> n;
for (int i = 0; i < n; i++) cin >> victims [i]. second >> victims [i]. first;
sort(victims , victims + n);
Problem-
Solving
Paradigms
Greedy
Algorithms
Moral: Sorting into a sensible order is often helpful. As is
Linear Sweep
drawing pictures.
Binary Search
Problem-
Solving
Paradigms
Problem statement
Greedy
Algorithms There are N ≤ 2000 countries, the i-th has ai ≤ 20
Linear Sweep delegates.
Binary Search
Problem-
Solving
Paradigms
Binary Search
Source Orac
Example problem: Restaurants 28
Problem-
Solving
Paradigms
Example Input
Greedy 3
Algorithms
4 3 3
Linear Sweep
Binary Search
3
5 2 3
Example Output 2
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms Observation 1: We should assign as many Australian
delegates as possible.
Greedy
Algorithms Proof: In any solution that does not, there is some
Linear Sweep restaurant with no Australian delegates and there is a
Binary Search starving Australian delegate.
We can then kick out any delegate for an Australian
delegate without making the solution any worse.
But where should we assign the Australian delegates?
Our main objective is to make it easier to seat the other
country’s delegates.
From some extreme examples, the bottleneck seems to be
the restaurants with few seats.
Example problem: Restaurants 31
Problem-
Solving Observation 2: We should assign delegates to the
Paradigms
restaurants with the most seats remaining.
Greedy Proof: Again, consider a solution that does not.
Algorithms
Linear Sweep
Then we skip restaurant i for a restaurant j where bi > bj .
Binary Search But this means we can swap some delegate from
restaurant i with the Australian delegate in j while
preserving uniqueness.
By repeating these swaps, we obtain a solution just as
optimal except Observation 2 was obeyed.
Example problem: Restaurants 32
Problem-
Solving
Paradigms
Problem-
Solving Implementation
Paradigms
#include <bits/stdc ++.h>
using namespace std;
Greedy
Algorithms const int MAXN = 2005, MAXM = 2005;
int N, numDelegates [MAXN], M, numSeats [MAXN ];
Linear Sweep
int main () {
Binary Search cin >> N;
for (int i = 0; i < N; i++) cin >> numDelegates [i];
cin >> M;
for (int i = 0; i < M; i++) cin >> numSeats [i];
int starved = 0;
for (int i = 0; i < N; i++) {
int delegatesRemaining = numDelegates [i];
sort(numSeats , numSeats +M, greater <int >());
for (int j = 0; j < M; j++) {
if ( numSeats [j] > 0 && delegatesRemaining > 0) {
numSeats [j]--;
delegatesRemaining --;
}
}
starved += delegatesRemaining ;
}
cout << starved << '\n';
return 0;
}
Example problem: Restaurants 34
Problem-
Solving
Paradigms
Binary Search
O(NM log M) ≈ O(4mil · 11), fast enough.
Once you have some guess, you can try to prove it after.
Coordinate Compression 35
Problem-
Solving
Paradigms Most of the examples in class have coordinates only up to
100,000 or so. But for most examples this is just a
Greedy
Algorithms
niceness condition.
Linear Sweep
Problem-
Solving
Paradigms Coordinate compression is the idea of replacing each
coordinate by its rank among all coordinates. Hence we
Greedy preserve the relative order of values while making the
Algorithms
Linear Sweep
maximum coordinate O(N).
Binary Search
This reduces us to the case with bounded coordinates.
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms
Greedy
Algorithms
Linear Sweep
1 Greedy Algorithms
Binary Search
2 Linear Sweep
3 Binary Search
Binary Search 39
Problem-
Solving
Paradigms
Surprisingly powerful technique!
Greedy
Algorithms
Linear Sweep You should have seen binary search in the context of
Binary Search searching an array before.
Problem-
Solving
Paradigms
Binary Search
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms
Binary Search
Problem-
Solving
Paradigms
int x;
cin >> x;
bool found = binary_search (a, a+n, x);
cout << (found ? "found " : "did not find ") << x;
Aside: Binary Search Implementation 44
Problem-
Solving
Paradigms
int y;
Greedy cin >> y;
Algorithms int i = lower_bound (a, a+n, y) - a;
if (i < n)
Linear Sweep
cout << "a[" << i << "] = " << a[i] << " is the first entry to compare >= "
Binary Search << y;
else
cout << "all elements of a[] compare < " << y;
int z;
cin >> z;
int j = upper_bound (a,a+n,z) - a;
if (j < n)
cout << "a[" << j << "] = " << a[j] << " is the first entry to compare > "
<< z;
else
cout << "all elements of a[] compare <= " << z;
}
Decision Problems and Optimisation Problems 45
Problem-
Solving
Paradigms
Decision problems are of the form
Given some parameters including X, can you ...
Greedy
Algorithms
Linear Sweep
Binary Search
Optimisation problems are of the form:
What is the smallest X for which you can ...
Problem-
Solving Let f(X) be the outcome of the decision problem for a
Paradigms
given X, so f is an integer valued function with range
Greedy
{0, 1}.
Algorithms
It is sometimes (but not always) the case in such problems
Linear Sweep
that increasing X does not make it any harder for the
Binary Search
condition to hold (i.e: that if the condition holds with X
then it also holds with X + 1).
Thus f is all 0’s up to the first 1, after which it is all 1’s.
This is a monotonic function, so we can use binary search!
This technique of binary searching the answer, that is,
finding the smallest X such that f(X) = 1 using binary
search, is often called discrete binary search.
Overhead is just a factor of O(log A) where A is the range
of possible answers.
Example: Chocolate Bar 47
Problem-
Solving
Paradigms
Linear Sweep
friends. Break the bar into K contiguous pieces. The
Binary Search
overall happiness of the group is the minimum total
tastiness of any of these K pieces. What’s the maximum
overall happiness you can achieve?
Problem-
Solving
Paradigms
Sample Input:
Greedy
Algorithms 5 2
Linear Sweep 9 7 3 7 4
Binary Search
Sample Output:
14
Problem-
Solving
Paradigms
Greedy
Algorithms It is worth trying to approach the minimization problem
Linear Sweep directly, just to appreciate the difficulty.
Binary Search
Problem-
Solving
Paradigms We are asked to maximize the minimum sum of the K
pieces.
Greedy
Algorithms
Linear Sweep
Let’s turn this into asking about a decision problem.
Binary Search
Define b(X) to be True iff we can split the bar into K
pieces, each with sum at least X.
Problem-
Solving
Paradigms
Rephrased Problem: Define b(X) to be True iff we can
Greedy
split the bar into K pieces, each with sum at least X.
Algorithms What is the largest X such that b(X) is True?
Linear Sweep
Binary Search
Key(and trivial) Observation: b(X) is non-increasing.
Problem-
Solving
Paradigms
New Problem: Can I split the bar into K pieces, each
with sum at least A?
Greedy
Algorithms Note that we can rephrase this into a maximization
Linear Sweep question. Given each piece has sum at least A, what is the
Binary Search maximum number of pieces I can split the bar into?
Let’s try going one piece at a time. What should the first
piece look like?
Key Observation: It should be the minimum length
possible while having total ≥ A.
This applies for all the pieces.
So to get the maximum number of pieces needed, we
sweep left to right making each piece as short as possible.
Example: Chocolate Bar 53
Problem-
Solving
Paradigms
Problem-
Solving
Paradigms
int main () {
Greedy scanf("%d %d", &N, &K);
Algorithms for (int i = 0; i < N; i++) scanf("%lld", &bar[i]);
long long lo = 1;
Linear Sweep
long long hi = 1e12;
Binary Search long long ans = -1;
while (lo <= hi) {
long long mid = (lo + hi) / 2;
// Trying to find the highest value that is feasible :
if (canDo(mid)) {
ans = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
printf("%lld\n", ans);
}
Example: Chocolate Bar 55
Problem-
Solving Complexity? O(N log A) where A is max answer.
Paradigms
This problem and solution is very typical of binary search
Greedy
problems.
Algorithms
To start with, you are asked to maximize a value.
Linear Sweep
But we can rephrase it into maximizing a value that
Binary Search
satisfies a decision problem! In forming the decision
problem, you ask if the answer could be at least A, not
just exactly A.
Now with the minimum tastiness of each bar fixed, you
now switch to trying to maximize the number of pieces
you can make. And this can be greedied since we know
how small we can make each piece.
Notice why fixing A made the problem easier. Because we
had one less parameter influencing our choices and we
could make greedy decisions now.
Binary Search 56
Problem-
Solving
Paradigms One of the most common places binary search appears is
in problems that ask us to maximize the minimum of
Greedy something (or minimize the maximum of something).
Algorithms
Linear Sweep Another way to see if it’s useful is just to see if the
Binary Search quantity you are minimizing is monotone.
Until you get the hang of it, it’s worth just always trying
to apply it.
Problem-
Solving
Paradigms Ternary search also exists. It applies to finding the
maximum of a function that strictly increases to a peak,
Greedy stays the same, then strictly decreases. Note the strictlys.
Algorithms
Problem-
Solving
Paradigms Problem Statement: You have just created a robot that
will revolutionize RoboCup forever. Well 1D RoboCup at
Greedy
Algorithms least.
Linear Sweep
The robot starts at position 0 on a line and can perform
Binary Search
three types of moves:
L: Move left by 1 position.
R: Move right by 1 position.
S: Stand still.
Currently the robot already has a loaded sequence of
instructions.
You need to get the robot to position x. To do so, you can
replace a single contiguous subarray of the robot’s
instructions. What is the shortest subarray you can replace
to get the robot to position x?
Example: Robot Moves 59
Problem-
Solving
Paradigms Input Format: First line, 2 integers, n, x, the length of
the loaded sequence and the destination.
Greedy 1 ≤ |x| ≤ n ≤ 200, 000. The next line describes the loaded
Algorithms
Linear Sweep
sequence.
Binary Search
Sample Input:
5 -4
LRRLR
Sample Output:
4
Problem-
Solving
Paradigms
How would one do the problem directly?
Greedy
Algorithms
There is an O(n2 ) by trying all subsegments but we can’t
Linear Sweep
do better if we need to try all subsegments.
Binary Search
Problem-
Solving
Paradigms
Binary Search
Problem-
Solving
Paradigms Key Observation: In m instructions, the robot can move
to every square within distance m.
Greedy
Algorithms So we are reduced to finding if there is a subsegment of
Linear Sweep size m such that its removal leaves the robot within
Binary Search distance m of x.
Problem-
Solving
Paradigms #include <iostream >
using namespace std;
void precomp () {
for (int i = 0; i < n; i++) {
if (moves[i] == 'L')
delta[i] = -1;
if (moves[i] == 'S')
delta[i] = 0;
if (moves[i] == 'R')
delta[i] = 1;
}
Problem-
Solving Complexity: O(n log n).
Paradigms
Hopefully you can see the similarities between this
Greedy example and the earlier example.
Algorithms
Linear Sweep
Again, we started with a problem where approaching it
Binary Search directly was too slow.
But the problem naturally could be rephrased as finding
the minimum m such that a decision problem f(m) was
true.
So from that point onwards we only consider the decision
problem.
This still required some work but was more direct. The
idea of trying all subsegments of length m is relatively
straightforward. From that point on it was just trying to
optimize this problem with data structures.