You are on page 1of 33

Counting

Dice combinations
Your task is to count the number of ways to construct sum n by throwing a dice one or more
times. Each throw produces an outcome between 1 and 6. For example, if n=3, there are 4 ways:

1+1+1
1+2
2+1
3

Sol: -
Coin Combinations I
Consider a money system consisting of n coins. Each coin has a positive integer value. Your
task is to calculate the number of distinct ways you can produce a money sum x using the
available coins.

For example, if the coins are {2,3,5} and the desired sum is 9, there are 8 ways:

2+2+5
2+5+2
5+2+2
3+3+3
2+2+2+3
2+2+3+2
2+3+2+2
3+2+2+2
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

using vi = vector<int>;

#define pb push_back

#define rsz resize

#define all(x) begin(x), end(x)

#define sz(x) (int)(x).size()

using pi = pair<int, int>;

#define f first

#define s second

#define mp make_pair

void setIO(string name = "") { // name is nonempty for USACO file I/O

ios_base::sync_with_stdio(0);

cin.tie(0); // see Fast Input & Output

if (sz(name)) {

freopen((name + ".in").c_str(), "r", stdin); // see Input & Output

freopen((name + ".out").c_str(), "w", stdout);

}
ll dp[1000001];

const int MOD = (int)1e9 + 7;

int main() {

int n, x;

cin >> n >> x;

vi coins(n);

for (int i = 0; i < n; i++) { cin >> coins[i]; }

dp[0] = 1;

for (int weight = 0; weight <= x; weight++) {

for (int i = 1; i <= n; i++) {

if (weight - coins[i - 1] >= 0) {

dp[weight] += dp[weight - coins[i - 1]];

dp[weight] %= MOD;

cout << dp[x] << '\n';

Grid Paths
Consider an n×n grid whose squares may have traps. It is not allowed to move to a square with
a trap. Your task is to calculate the number of paths from the upper-left square to the lower-right
square. You can only move right or down.

Input:

4
....
.*..
...*
*...
Output:3

#include <iostream>

using namespace std;

const int DIR_LEN = 4;

int dr[DIR_LEN] = {-1, 0, 1, 0};

int dc[DIR_LEN] = {0, 1, 0, -1};

const int PATH_LEN = 48; // length of all possible paths

int p[PATH_LEN];

const int GRID_SIZE = 9;

// added border to all four sides so a 7x7 becomes a 9x9

bool onPath[GRID_SIZE][GRID_SIZE];

int tryPath(int pathIdx, int curR, int curC) {

// Optimization 3

if ((onPath[curR][curC - 1] && onPath[curR][curC + 1]) &&

(!onPath[curR - 1][curC] && !onPath[curR + 1][curC]))

return 0;

if ((onPath[curR - 1][curC] && onPath[curR + 1][curC]) &&

(!onPath[curR][curC - 1] && !onPath[curR][curC + 1]))

return 0;

if (curR == 7 && curC == 1) { // reached endpoint before visiting all

if (pathIdx == PATH_LEN) return 1;

return 0;

if (pathIdx == PATH_LEN) return 0;

int ret = 0;

onPath[curR][curC] = true;

// turn already determined:

if (p[pathIdx] < 4) {

int nxtR = curR + dr[p[pathIdx]];

int nxtC = curC + dc[p[pathIdx]];

if (!onPath[nxtR][nxtC]) ret += tryPath(pathIdx + 1, nxtR, nxtC);

// see Java solution for optimization 4 implementation


else { // iterate through all four possible turns

for (int i = 0; i < DIR_LEN; i++) {

int nxtR = curR + dr[i];

int nxtC = curC + dc[i];

if (onPath[nxtR][nxtC]) continue;

ret += tryPath(pathIdx + 1, nxtR, nxtC);

// reset and return

onPath[curR][curC] = false;

return ret;

int main() {

string line;

getline(cin, line);

// convert path to ints

for (int i = 0; i < PATH_LEN; i++) {

char cur = line[i];

if (cur == 'U') p[i] = 0;

else if (cur == 'R') p[i] = 1;

else if (cur == 'D') p[i] = 2;

else if (cur == 'L') p[i] = 3;

else p[i] = 4; // cur == '?'

// set borders of grid

for (int i = 0; i < GRID_SIZE; i++) {

onPath[0][i] = true;

onPath[8][i] = true;

onPath[i][0] = true;

onPath[i][8] = true;

// initialize the inside of the grid to be completely empty

for (int i = 1; i <= 7; i++) {


for (int j = 1; j <= 7; j++) { onPath[i][j] = false; }

int startIdx = 0;

int startR = 1;

int startC = 1; // always start path at (1, 1)

int ans = tryPath(startIdx, startR, startC);

cout << ans << endl;

Optimization

Maximum Increase
You are given an array consisting of n integers. Your task is to find the maximum length of an
increasing subarray of the given array. A subarray is the sequence of consecutive elements of
the array. Subarray is called increasing if each element of this subarray is strictly greater than
previous.
Input:
5
1 7 2 11 15

Output: 3

​ #include<bits/stdc++.h>

​ using namespace std;

​ #define ll long long

​ #define flash() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

​ int main()

​ {

​ flash();

​ ll n;

​ cin >> n;

​ ll cl = 0 , ml = 1 , ce = 0;

​ for(ll i = 0 ; i<n ; i++)


​ {

​ ll x;

​ cin >> x;

​ if(ce < x)

​ {

​ ce = x;

​ cl++;

​ ml = max(cl , ml);

​ }

​ else

​ {

​ ce = x;

​ cl = 1;

​ }

​ }

​ cout << ml << endl;

​ return 0;

​ }

BerSu Ball
Berland State University is hosting a ballroom dance in celebration of its 100500th anniversary!
n boys and m girls are already busy rehearsing waltz, minuet, polonaise, and quadrille moves.
We know that several boy&girl pairs are going to be invited to the ball. However, the partners'
dancing skills in each pair must differ by at most one. For each boy, we know his dancing skills.
Similarly, for each girl, we know her dancing skills. Write a code that can determine the largest
possible number of pairs that can be formed from n boys and m girls.

Input:
4
1462
5
51579
Output: 3

​ #include<bits/stdc++.h>

​ using namespace std;

​ typedef long long ll;

​ #define ull unsigned long long

​ #define flash() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

​ const long long int MOD = 1e9 + 7;

​ const long long int INF = 1e18;

​ const long long int MAX = 1e9;

​ int main()

​ {

​ flash();

​ ll n , m;

​ cin >> n;

​ vector<ll> v(102 , 0) , vec;

​ for(ll i = 0 ; i < n ; i++)

​ {

​ ll x;

​ cin >> x;

​ v[x]++;

​ }

​ cin >> m;

​ for(ll i = 0 ; i < m ; i++)

​ {

​ ll x;

​ cin >> x;

​ vec.push_back(x);

​ }

​ sort(vec.begin() , vec.end());

​ ll cnt = 0;

​ for(ll i = 0 ; i < m ; i++)


​ {

​ if(v[vec[i] - 1] >= 1)

​ {

​ v[vec[i] - 1]--;

​ cnt++;

​ }

​ else

​ {

​ if(v[vec[i]] >= 1)

​ {

​ v[vec[i]]--;

​ cnt++;

​ }

​ else

​ {

​ if(v[vec[i] + 1] >= 1)

​ {

​ v[vec[i] + 1]--;

​ cnt++;

​ }

​ else

​ {

​ continue;

​ }

​ }

​ }

​ }

​ cout << cnt << endl;

​ return 0;

​ }
Removing digits
You are given an integer n.On each step, you may subtract one of the digits from the number.
How many steps are required to make the number equal to 0?

Input:
27

Output:
5
Explanation: An optimal solution is 27→20→18→10→9→0.

#include <bits/stdc++.h>

using namespace std;

int main() {

int n;

cin >> n;

vector<int> dp(n+1,1e9);

dp[0] = 0;

for (int i = 0; i <= n; i++) {

for (char c : to_string(i)) {

dp[i] = min(dp[i], dp[i-(c-'0')]+1);

cout << dp[n] << endl;

Minimizing coins
Consider a money system consisting of n coins. Each coin has a positive integer value. Your
task is to produce a sum of money x using the available coins in such a way that the number of
coins is minimal. For example, if the coins are {1,5,7} and the desired sum is 11, an optimal
solution is 5+5+1 which requires 3 coins. The first input line has two integers n
and x: the number of coins and the desired sum of money.
Input:
3 11
157
Output: 3

#include <bits/stdc++.h>

using namespace std;

int main() {

int n, target;

cin >> n >> target;

vector<int> c(n);

for (int&v : c) cin >> v;

vector<int> dp(target+1,1e9);

dp[0] = 0;

for (int i = 1; i <= target; i++) {

for (int j = 0; j < n; j++) {

if (i-c[j] >= 0) {

dp[i] = min(dp[i], dp[i-c[j]]+1);

cout << (dp[target] == 1e9 ? -1 : dp[target]) << endl;

}
Book shop
You are in a book shop which sells n different books. You know the price and number of pages
of each book. You have decided that the total price of your purchases will be at most x. What is
the maximum number of pages you can buy? You can buy each book at most once.
The first input line contains two integers n and x: the number of books and the maximum total
price.The next line contains n integers h1,h2,…,hn: the price of each book. The last line contains
n integers s1,s2,…,sn : the number of pages of each book.
Input:
4 10
4853
5 12 8 1
Output: 13

Explanation: You can buy books 1 and 3. Their price is 4+5=9 and the number of pages is
5+8=13.

#include <bits/stdc++.h>

using namespace std;

int main() {

int n, x;

cin >> n >> x;

vector<int> price(n), pages(n);

for (int&v : price) cin >> v;

for (int&v : pages) cin >> v;

vector<vector<int>> dp(n+1,vector<int>(x+1,0));

for (int i = 1; i <= n; i++) {

for (int j = 0; j <= x; j++) {

dp[i][j] = dp[i-1][j];

int left = j-price[i-1];


if (left >= 0) {

dp[i][j] = max(dp[i][j], dp[i-1][left]+pages[i-1]);

cout << dp[n][x] << endl;

Stone game
Polycarp is playing a new computer game. This game has ‘n’ stones in a row. The stone on the
position i has integer power ai. The powers of all stones are distinct. Each turn Polycarp can
destroy either stone on the first position or stone on the last position (in other words, either the
leftmost or the rightmost stone). When Polycarp destroys the stone it does not exist any more.
Now, Polycarp wants two achievements. He gets them if he destroys the stone with the least
power and the stone with the greatest power. Help Polycarp find out what is the minimum
number of moves he should make in order to achieve his goal. For example, if n=5 and
a=[1,5,4,3,2], then Polycarp could make the following moves:

I.Destroy the leftmost stone. After this move a=[5,4,3,2];


II. Destroy the rightmost stone. After this move a=[5,4,3]
III.Destroy the leftmost stone. After this move a=[4,3]. Polycarp destroyed the stones with the
greatest and least power, so he can end the game.

#include <bits/stdc++.h>

int main() {

std::ios::sync_with_stdio(false);

std::cin.tie(nullptr);

int t;

std::cin >> t;

while (t--) {

int n;
std::cin >> n;

std::vector<int> a(n);

for (int i = 0; i < n; i++) {

std::cin >> a[i];

int u = std::find(a.begin(), a.end(), 1) - a.begin();

int v = std::find(a.begin(), a.end(), n) - a.begin();

if (u > v) {

std::swap(u, v);

int ans = std::min({u + 1 + n - v, n - u, v + 1});

std::cout << ans << "\n";

return 0;

Kefa and first steps


Kefa decided to make some money doing business on the Internet for exactly n days. He knows
that on the i-th day (1 ≤ i ≤ n) he makes ai money. Kefa loves progress, that's why he wants to
know the length of the maximum non-decreasing subsegment in sequence ai. Let us remind you
that the subsegment of the sequence is its continuous fragment. A subsegment of numbers is
called non-decreasing if all numbers in it follow in the non-decreasing order. Help Kefa cope with
this task!

#include <bits/stdc++.h>

using namespace std;

int main()

int n;

cin >> n;
int res = 0;

int cnt = 0;

int p = 0;

while (n--)

int a;

cin >> a;

if (a >= p)

cnt++;

else

cnt = 1;

res = max(res, cnt);

p = a;

cout << res << '\n';

Feasibility

Fair Division
Alice and Bob received n candies from their parents. Each candy weighs either 1 gram or 2
grams. Now they want to divide all candies among themselves fairly so that the total weight of
Alice's candies is equal to the total weight of Bob's candies. Check if they can do that. Note that
candies are not allowed to be cut in half.
Maximum Increase
You are given an array consisting of n integers. Your task is to find the maximum length of an
increasing subarray of the given array. A subarray is the sequence of consecutive elements of
the array. Subarray is called increasing if each element of this subarray is strictly greater than
the previous.

#include <bits/stdc++.h>
using namespace std;

// function to find the length of longest increasing contiguous subarray

int lenOfLongIncSubArr(int arr[], int n)

// 'max' to store the length of longest increasing subarray 'len' to store the lengths
of longest increasing subarray at different instants of time

int max = 1, len = 1;

// traverse the array from the 2nd element

for (int i=1; i<n; i++)


{

// if current element if greater than previous element, then this element helps
in building //up the previous increasing subarray encountered so far

if (arr[i] > arr[i-1])

len++;

else

// check if 'max' length is less than the length of the current


increasing subarray.

//If true, then update 'max'

if (max < len)

max = len;

// reset 'len' to 1 as from this element again the length of the new
increasing

// subarray is being calculated

len = 1;

// comparing the length of the last increasing subarray with 'max'

if (max < len)

max = len;

// required maximum length

return max;

// Driver program to test above

int main()

int arr[] = {5, 6, 3, 5, 7, 8, 9, 1, 2};

int n = sizeof(arr) / sizeof(arr[0]);

cout << "Length = "


<< lenOfLongIncSubArr(arr, n);

return 0;

The cake is a lie


There is a n×m grid. You are standing at cell (1,1) and your goal is to finish at cell (n,m). You can
move to the neighboring cells to the right or down. In other words, suppose you are standing in a
cell (x,y).

You can:
move right to the cell (x,y+1)— it costs x burles;
move down to the cell (x+1,y) — it costs y burles.
Can you reach cell (n,m) spending exactly k burles?

Code:
#include <bits/stdc++.h>

using namespace std;

int main()

long long int t;

cin >> t;

while (t--)

long long int n, m, k;

cin >> n >> m >> k;

long long int costOf1 = (m - 1) * 1;

long long int costOfColoum = (n - 1) * m;

long long int totalcost = costOf1 + costOfColoum;

if (totalcost == k)

cout << "YES\n";


else

cout << "NO\n";

return 0;

Matching

Similar pairs
We call two numbers x and y similar if they have the same parity (the same remainder when
divided by 2), or if |x−y|=1. For example, in each of the pairs (2,6), (4,3), (11,7), the numbers are
similar to each other, and in the pairs (1,4), (3,12), they are not.

You are given an array of n (n is even) positive integers. Check if there is such a partition of the
array into pairs that each element of the array belongs to exactly one pair and the numbers in
each pair are similar to each other.

For example, for the array a=[11,14,16,12], there is a partition into pairs (11,12) and (14,16). The
numbers in the first pair are similar because they differ by one, and in the second pair, they are
both even.
Brevity is the soul of wit
As we communicate, we learn much new information. However, the process of communication
takes too much time. It becomes clear if we look at the words we use in our everyday speech.
We can list many simple words consisting of many letters: "information", "technologies",
"university", "construction", "conservatoire", "refrigerator", "stopwatch", "windowsill", "electricity",
"government" and so on. Of course, we can continue listing those words ad infinitum.
Fortunately, the solution for that problem has been found. To make our speech clear and brief,
we should replace the initial words with those that resemble them but are much shorter. This
idea hasn't been brought into life yet, that's why you are chosen to improve the situation. Let's
consider the following formal model of transforming words: we shall assume that one can use n
words in a chat. For each word we shall introduce a notion of its shorter variant. We shall define
a shorter variant of an arbitrary word s as such word t, that meets the following conditions: it
occurs in s as a subsequence, its length ranges from one to four characters. In other words, the
word t consists at least of one and at most of four characters that occur in the same order in the
word s. Note that those characters do not necessarily follow in s immediately one after another.
You are allowed not to shorten the initial word if its length does not exceed four characters. You
are given a list of n different words. Your task is to find a set of their shortened variants. The
shortened variants of all words from the list should be different

​ #include <iostream>

​ #include <cstdio>

​ #include <cstdlib>

​ #include <string>

​ #include <vector>

​ #include <map>

​ using namespace std;

​ const int N = 220;

​ int n, m;

​ map<string, int> names;

​ string names2[N * N];

​ vector<int> g[N];

​ vector<string> getStr(string s)

​ {

​ vector<string> res;

​ int l = (int)s.length();

​ for (int i = 0; i < l; i++)

​ res.push_back(s.substr(i, 1));

​ for (int i = 0; i < l; i++)

​ for (int j = i + 1; j < l; j++)

​ res.push_back(s.substr(i, 1) + s.substr(j, 1));

​ for (int i = 0; i < l; i++)

​ for (int j = i + 1; j < l; j++)

​ for (int k = j + 1; k < l; k++)

​ res.push_back(s.substr(i, 1) + s.substr(j, 1) +
s.substr(k, 1));

​ for (int i = 0; i < l; i++)

​ for (int j = i + 1; j < l; j++)

​ for (int k = j + 1; k < l; k++)

​ for (int p = k + 1; p < l; p++)

​ res.push_back(s.substr(i, 1) + s.substr(j, 1)
+ s.substr(k, 1) + s.substr(p, 1));

​ return res;

​ }

​ int getNum(string s)

​ {

​ if (names.count(s) == 0)

​ {

​ names[s] = m;

​ names2[m] = s;

​ return m++;

​ }

​ else

​ return names[s];
​ }

​ void read()

​ {

​ cin >> n;

​ string s;

​ for (int i = 0; i < n; i++)

​ {

​ cin >> s;

​ vector<string> tmp = getStr(s);

​ for (int j = 0; j < (int)tmp.size(); j++)

​ {

​ int x = getNum(tmp[j]);

​ g[i].push_back(x);

​ }

​ }

​ if (m >= N * N) throw;

​ return;

​ }

​ int xdouble[N], ydouble[N * N];

​ bool xlabel[N];

​ bool dfs(int x)

​ {

​ if (xlabel[x]) return false;

​ xlabel[x] = 1;

​ for (int i = 0; i < (int)g[x].size(); i++)

​ {

​ int y = g[x][i];

​ if (ydouble[y] == -1 || dfs(ydouble[y]))

​ {

​ xdouble[x] = y;

​ ydouble[y] = x;
​ return true;

​ }

​ }

​ return false;

​ }

​ void solve()

​ {

​ for (int i = 0; i < n; i++)

​ xdouble[i] = -1;

​ for (int i = 0; i < m; i++)

​ ydouble[i] = -1;

​ for (int i = 0; i < n; i++)

​ {

​ for (int j = 0; j < n; j++)

​ xlabel[j] = 0;

​ dfs(i);

​ }

​ return;

​ }

​ void printAns()

​ {

​ bool ok = true;

​ for (int i = 0; i < n; i++)

​ if (xdouble[i] == -1)

​ ok = false;

​ if (!ok)

​ {

​ printf("-1\n");

​ return;

​ }

​ for (int i = 0; i < n; i++)

​ cout << names2[xdouble[i]] << endl;


​ return;

​ }

​ int main()

​ {

​ freopen("input.txt", "r", stdin);

​ freopen("output.txt", "w", stdout);

​ read();

​ solve();

​ printAns();

​ return 0;

​ }

Angels and demons


It's the year 21546 AD, and due to the increased population (you wouldn't believe me if I gave you
the actual numbers), land has become very expensive. Because of the lack of space, Heaven
and Hell were built in the same area. The area can be represented as a grid of X × Y unit squares.
Some of the squares were captured by the Devil (and thus belong to Hell); the rest is the
Almighty's property. On each square, a room has been built with transparent glass walls.
However, some of the heavenly rooms are already occupied by Angels. For security purposes,
rooms occupied by Angels have concrete opaque walls. Recently many fighters were killed in a
tournament. Fighting is no longer considered cruel, so all fighters deserve spots in heaven.
However, because of the space shortage, all of them may not be able to receive a spot in
heaven. The fighters still hold a grudge against each other, so a fighter cannot be placed in a
room from which he can see any other fighter. A fighter can only see in four cardinal directions
(North, South, East, and West). He cannot look diagonally or in any other direction. Find the
maximum number of fighters who can have a heavenly room.

Code: -

#include <cstdio>

#include <vector>
#include <algorithm>

using namespace std;

struct bipartite_graph

int V1, V2, *match;

vector<int> *L;

bool *visited;

bipartite_graph(int MAX_V1, int MAX_V2)

L = new vector<int>[MAX_V1];

visited = new bool[MAX_V2];

match = new int[MAX_V2];

void clear(int _V1, int _V2)

V1 = _V1;

V2 = _V2;

for (int i = 0; i < V1; ++i)

L[i].clear();

void add_edge(int v1, int v2)

L[v1].push_back(v2);

bool dfs(int u)

for (int i = L[u].size() - 1; i >= 0; --i)

int v = L[u][i];

if (!visited[v])

{
visited[v] = true;

if (match[v] == -1 || dfs(match[v]))

match[v] = u;

return true;

return false;

int maximum_matching()

int ans = 0;

fill(match, match + V2, -1);

for (int i = 0; i < V1; ++i)

fill(visited, visited + V2, false);

ans += dfs(i);

return ans;

} G(150 * 300, 150 * 300);

int main()

int T, R, C;

scanf("%d", &T);

char M[300][600];

int hor[300][300], ver[300][300], V1, V2;

for (int tc = 1; tc <= T; ++tc)

scanf("%d %d", &R, &C);

for (int i = 0; i < R; ++i)


for (int j = 0; j < C; ++j)

scanf(" %c", &M[i][j]);

hor[i][j] = ver[i][j] = -1;

V1 = V2 = 0;

for (int i = 0; i < R; ++i)

for (int j = 0; j < C; ++j)

if (M[i][j] != 'A')

if (j == 0 || M[i][j - 1] == 'A')

hor[i][j] = V1++;

else

hor[i][j] = hor[i][j - 1];

if (i == 0 || M[i - 1][j] == 'A')

ver[i][j] = V2++;

else

ver[i][j] = ver[i - 1][j];

G.clear(V1, V2);

for (int i = 0; i < R; ++i)

for (int j = 0; j < C; ++j)

if (M[i][j] == 'H')

G.add_edge(hor[i][j], ver[i][j]);

printf("%d\n", G.maximum_matching());

return 0;

}
Process : -

The problem can be formulated as a bipartite matching problem with two sets of vertices:

Set A - The set of available heavenly rooms

Set B - The set of fighters

The edges between the vertices will represent the conditions required for a fighter to be placed
in a particular room. Specifically, an edge will be drawn between a heavenly room vertex and a
fighter vertex if and only if the fighter can occupy the room without violating the condition of not
being able to see any other fighter.

Let us define the variables:

Let X and Y be the number of unit squares in the horizontal and vertical direction respectively.
Let A be the set of available heavenly rooms. It contains X * Y vertices. Let B be the set of
fighters. It contains the number of fighters who participated in the tournament.

We will now describe the edges that will be drawn between the vertices. An edge will be drawn
between a heavenly room vertex and a fighter vertex if and only if the room is not already
occupied and the fighter can be placed in the room without violating the condition of not being
able to see any other fighter. The edge will be directed from the heavenly room vertex to the
fighter vertex, as each room can only accommodate one fighter. Once the bipartite graph is
constructed, we can find the maximum number of fighters who can have a heavenly room by
finding the maximum cardinality matching in the graph. The maximum cardinality matching will
correspond to the maximum number of fighters who can be placed in heavenly rooms without
violating the condition of not being able to see any other fighter.
We have n threads with each one having a bead. We want to vertically line up all the
beads by moving them along the threads. The objective is to minimize the total distance
moved. For example, we can align the beads shown in Fig. 1 by moving tby he second
bead 3 units to the left; fourth and fifth bead by one unit to the left and right,
respectively. Given n numbers denoting the positions of beads, design a linear time
algorithm to find the minimum total distance the beads have to be moved in order to line
them up.

To find the minimum total distance to line up the beads, we need to find the median position of
all the beads and move each bead to that position. This can be done in linear time as follows:

● Sort the list of positions.


● Find the median position (either by taking the middle element if n is odd, or by taking the
average of the middle two elements if n is even).
● Calculate the total distance that each bead needs to move to reach the median position.
● Return the sum of these distances as the minimum total distance.

1. Given a set of n points on a xy-plane find the pair of points whose connecting line
segment has the maximum slope. The algorithm must run in O(n log n).

To find the pair of points whose connecting line segment has the maximum slope, we
can use a divide and conquer approach that is similar to the merge sort algorithm:

● Divide the set of points into two roughly equal subsets.


● Recursively find the pair of points with the maximum slope in each subset.
● Find the pair of points with the maximum slope that cross the boundary between
the two subsets.
● Return the pair of points with the maximum slope out of the three pairs found.

To find the pair of points with the maximum slope that cross the boundary, we need to consider
all pairs of points where one point is in the left subset and the other is in the right subset. We
can sort the points in each subset by their y-coordinate and then only consider pairs where the
difference in y-coordinate is less than the maximum slope found in the previous step.

This algorithm has a time complexity of O(n log n) because each recursive call involves dividing
the set of points into two subsets of roughly half the size and each subset is sorted in O(n log n)
time.

2. We are given the heights of n men and n women. Give an O(n log n) algorithm to pair
them so that the average height difference in a pair is minimized.

To pair the n men with the n women to minimize the average height difference in a pair, we can
use a modified merge sort algorithm:

● Sort the list of heights of the men and women separately.


● Merge the two sorted lists into a single sorted list of pairs. To do this, we can start with
an empty list of pairs and iterate through the sorted lists of men and women in parallel,
comparing the heights of the current man and woman and adding the pair with the
smallest height difference to the list of pairs. If there is a tie between two pairs, we can
break the tie arbitrarily.
● Return the list of pairs.

The time complexity of this algorithm is O(n log n) because the sorting step takes O(n log n)
time and the merging step takes O(n) time.

Proof of correctness:

The algorithm pairs each man with the woman whose height is closest to his own height, among
all possible pairs. This is because the sorted list of pairs is constructed by choosing, for each
man, the woman whose height is closest to his own height among all remaining women.
Therefore, the algorithm minimizes the average height difference in a pair, because each pair
consists of the man and woman with the smallest height difference between them.

You might also like