HackerX
Difficulty: Hard

**Update:** A slight modification in the problem statement (see below)  

Evil Nation A is angry and plans to launch **N** guided-missiles at the peaceful Nation B in an attempt to wipe out all of Nation B's people. Nation A's missile _i_ will arrive in nation B at time t<sub>i</sub>. Missile _i_ communicates with its headquarters by unique radio signals with a frequency equal to f<sub>i</sub>. Can you help the peaceful Nation B survive by building a defensive system that will stop the missiles dead in the sky?

**Defensive system:**  

The only way to defend Nation B from the attacking missile is by counter attacking them with a _hackerX_ missile. You have a lot of _hackerX_ missiles and each one of them has its own radio frequency. An individual _hackerX_ missile can destroy Evil Nation A’s attacking missile if the radio frequency of both of the missiles match. Each _hackerX_ missile can be used an indefinite number of times. Its invincible and doesn't get destroyed in the collision.

The good news is you can adjust the frequency of the _hackerX_ missile to match the evil missiles' frequency. When changing the _hackerX_ missile's initial frequency fA to the new defending frequency fB, you will need \|fB - fA\| units of time to do. 

<strike>Each _hackerX_ missile can only destroy one of Nation A's missile at a time. So if two evil missiles with same frequency arrive at the same time, you need at least two _hackerX_ missiles with the same frequency as the evil missiles to avoid damage.</strike> 

If two evil missles with same frequency arrive at the same time, we can destroy them both with one _hackerX_ missile. You can set the frequency of a _hackerX_ missile to any value when its fired.  

What is the minimum number of _hackerX_ missiles you must launch to keep Nation B safe?


**Input Format:**  
The first line contains a single integer **N** denoting the number of missiles.   
This is followed by **N** lines each containing two integers t<sub>i</sub> and f<sub>i</sub> denoting the time & frequency of the i<sup>th</sup> missile.

**Output Format:**  
A single integer denoting the minimum number of _hackerX_ missiles you need to defend the nation.

**Constraints:**  
1 <=  N  <= 100000  
0 <= t<sub>i</sub> <= 100000  
0 <= f<sub>i</sub> <= 100000  
t<sub>1</sub> <= t<sub>2</sub> <= ... <= t<sub>N</sub>  

**Sample Input #00**  

    4
    1 1
    2 2
    3 1
    5 1

**Sample Output #00**  

    1

**Explanation #00**

A _HackerX_ missile is launched at t = 1 with a frequency f = 1, and destroys the first missile. It re-tunes its frequency to f = 2 in 1 unit of time, and destroys the missile that is going to hit Nation B at t = 2. It re-tunes its frequency back to 1 in 1 unit of time and destroys the missile that is going to hit the nation at t = 3. It is relaunched at t = 5 with f = 1 and destroys the missile that is going to hit nation B at t = 5. Hence, you need only 1 _HackerX_ to protect nation B. 

**Sample Input #01**  
 
    4
    1 1
    2 3
    3 1
    5 1
 
**Sample Output #01**  
 
    2
 
**Explanation #01**
 
Destroy 1 missile at t = 1, f = 1. now at t = 2, there is a missile with frequency 3. The launched missile takes 2 units of time to destroy this, hence we need a new hackerX missile to destroy this one. The first hackerX missile can destroy the 3rd missile which has the same frequency as itself. The same hackerX missile destroys the missile that is hitting its city at t = 5. Thus, we need atleast 2 hackerX missiles. 

Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:
#
# Complete the 'missileDefend' function below.
#
# The function is expected to return an INTEGER.
# The function accepts 2D_INTEGER_ARRAY missiles as parameter.
#

def missileDefend(missiles):
    # Write your code here



Editorial: hackerX  : Oct 20/20 Editorial
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p><strong>Problem</strong>: <a href="https://www.hackerrank.com/contests/oct13/challenges/missile-defend">hackerX</a></p>

<p><strong>Difficulty</strong>: Medium-Hard</p>

<p><strong>Required Knowledge</strong>:  Minimum Path cover, Dilworth's theorem</p>

<p><strong>Problem Setter</strong>: <a href="https://www.hackerrank.com/wanbo">Wanbo</a></p>

<p><strong>Problem Tester</strong>: <a href="https://www.hackerrank.com/cpcs">Cao Peng</a>, <a href="https://www.hackerrank.com/khongor">Khongor</a></p>

<p><strong>Approach</strong></p>

<p>What's the requirement if one hackerX missiles can defend both (ti, fi) and (tj, fj) when ti &lt;= tj?  </p>

<p>tj - ti &gt;= \|fi - fj\| (because you just need \|fi - fj\| units time to change the frequency from fi to fj, 
so you can defend tj after defend ti by this hackerX missiles if you need. 
So if we regard every coming missiles (ti, fi) as an vertex i, and if tj - ti &gt;= \|fi - fj\| then we add an edge from i to j, 
this edge indicates that one hackerX can defend the j<sup>th</sup> missile after defending the i<sup>th</sup> missile.  </p>

<p>So the solution for this challenge seems obvious, we just need to find the "Minimum Path Cover"(Can be changed to MaxFlow problem) of this graph. </p>

<p>But n can be as large as 100000, and there are at most O(n<sup>2</sup>) edges, even generating the graph will get TLE, we need to optimize our solution. </p>

<p>We haven't taken advantage of the particularity of this graph in the previous analysis, we just look this as a more general problem.</p>

<p>tj - ti &gt;= \|fi - fj\|
&lt;==&gt;
If fi &lt; fj,  tj - ti &gt;= fj - fi ==&gt; ti - fi &lt;= tj - fj ==&gt; Ai &lt;= Aj (Ai = ti - fi) 
If fi &gt;= fj, tj - ti &gt;= fi - fj ==&gt; ti + fi &lt;= tj + fj ==&gt; Bi &lt;= Bj (Bi = ti + fi)</p>

<p>Can we remove some constraints?</p>

<ol>
<li>ti &lt;= tj</li>
<li>If fi &lt; fj,   Ai &lt;= Aj ==&gt; Ai + 2 * fi &lt;= Aj + 2 * fj ==&gt; Bi &lt;= Bj</li>
<li>If fi &gt;= fj,  Bi &lt;= Bj ==&gt; Bi - 2 * fi &lt;= Bj - 2 * fj ==&gt; Ai &lt;= Aj</li>
</ol>

<p>We can combine 2) with 3) to "Ai &lt;= Aj &amp;&amp; Bi &lt;= Bj"
Ai + Bi &lt;= Aj + Bj ==&gt; ti &lt;= tj ==&gt; ti &lt;= tj can be removed. </p>

<p>==&gt;</p>

<p>edge(i-&gt;j) &lt;==&gt; Ai &lt;= Aj &amp;&amp; Bi &lt;= Bj</p>

<p>We need to find the minimum path cover in the graph which edge(i-&gt;j) &lt;==&gt; Ai &lt;= Aj &amp;&amp; Bi &lt;= Bj. </p>

<p>According to <a href="https://en.wikipedia.org/wiki/Dilworth%27s_theorem">Dilworth's theorem</a>, the minimum path cover in this graph is equal to the longest anti-chain.
So we just need to choose a maximum vertexes subset from the graph, where any of two do not have an edge. 
1. Sort the (Ai, Bi) by the first key value Ai, if Ai == Aj, then smaller Bi comes first. 
2. The longest decreasing subsequence of Bi will be the answer.(This is a very classic question that can be solved by O(nlgn).</p>

<p><strong>Problem Setter Code</strong>:</p>

<pre><code>#include &lt;map&gt;
#include &lt;set&gt;
#include &lt;list&gt;
#include &lt;queue&gt;
#include &lt;deque&gt;
#include &lt;stack&gt;
#include &lt;bitset&gt;
#include &lt;vector&gt;
#include &lt;ctime&gt;
#include &lt;cmath&gt;
#include &lt;cstdio&gt;
#include &lt;string&gt;
#include &lt;cstring&gt;
#include &lt;cassert&gt;
#include &lt;numeric&gt;
#include &lt;iomanip&gt;
#include &lt;sstream&gt;
#include &lt;fstream&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;
typedef long long       LL;
typedef pair&lt;int, int&gt;  PII;
typedef pair&lt;LL, LL&gt;    PLL;
typedef vector&lt;int&gt;     VI;
typedef vector&lt;LL&gt;      VL;
typedef vector&lt;PII&gt;     VPII;
typedef vector&lt;PLL&gt;     VPLL;
#define MM(a,x) memset(a,x,sizeof(a));
#define ALL(x)  (x).begin(), (x).end()
#define P(x)    cerr&lt;&lt;"["#x&lt;&lt;" = "&lt;&lt;(x)&lt;&lt;"]\n"
#define PP(x,i) cerr&lt;&lt;"["#x&lt;&lt;i&lt;&lt;" = "&lt;&lt;x[i]&lt;&lt;"]\n"
#define P2(x,y) cerr&lt;&lt;"["#x" = "&lt;&lt;(x)&lt;&lt;", "#y" = "&lt;&lt;(y)&lt;&lt;"]\n"
#define TM(a,b) cerr&lt;&lt;"["#a" -&gt; "#b": "&lt;&lt;1e3*(b-a)/CLOCKS_PER_SEC&lt;&lt;"ms]\n";
#define FOR(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define rep(i, n) for(int i = 0; i &lt; n; i++)
#define UN(v) sort(ALL(v)), v.resize(unique(ALL(v))-v.begin())
#define mp make_pair
#define pb push_back
#define x first
#define y second
struct _ {_() {ios_base::sync_with_stdio(0);}} _;
template&lt;class T&gt; void PV(T a, T b) {while(a != b)cout &lt;&lt; *a++, cout &lt;&lt; (a != b ? " " : "\n");}
template&lt;class T&gt; inline bool chmin(T &amp;a, T b) {return a &gt; b ? a = b, 1 : 0;}
template&lt;class T&gt; inline bool chmax(T &amp;a, T b) {return a &lt; b ? a = b, 1 : 0;}
template&lt;class T&gt; string tostring(T x, int len = 0) {stringstream ss; ss &lt;&lt; x; string r = ss.str(); if(r.length() &lt; len) r = string(len - r.length(), '0') + r; return r;}
template&lt;class T&gt; void convert(string x, T&amp; r) {stringstream ss(x); ss &gt;&gt; r;}
template&lt;class A, class B&gt; ostream&amp; operator&lt;&lt;(ostream &amp;o, pair&lt;A, B&gt; t) {o &lt;&lt; "(" &lt;&lt; t.x &lt;&lt; ", " &lt;&lt; t.y &lt;&lt; ")"; return o;}
const int inf = 0x3f3f3f3f;
const int mod = int(1e9) + 7;
const int N = 111111;

int t[N], f[N];
int d[N];
int n;


int LIS(VI v) {
    fill(d, d + n, 1);
    for(int i = 0; i &lt; n; i++)
        for(int j = 0; j &lt; i; j++)
            if(v[i] &gt; v[j]) chmax(d[i], d[j] + 1);
    int res = 0;
    for(int i = 0; i &lt; n; i++) chmax(res, d[i]);
    return res;
}

int LIS1(VI v) {
    MM(d, 0x3f);
    d[1] = v[0];
    for(int i = 1; i &lt; v.size(); i++) {
        int t = upper_bound(d + 1, d + N, v[i]) - d;
        if(t != 1 &amp;&amp; d[t - 1] &gt;= v[i]) continue;
        d[t] = v[i];
    }
    int res = 0;
    for(int i = 1; i &lt; N; i++) if(d[i] != inf) res = i;
    return res;
}

int main() {
    cin &gt;&gt; n;
    for(int i = 0; i &lt; n; i++) cin &gt;&gt; t[i] &gt;&gt; f[i];
    for(int i = 1; i &lt; n; i++) assert(t[i] &gt;= t[i - 1]);
    VI v;
    VPII vp;
    for(int i = 0; i &lt; n; i++) vp.pb(mp(t[i] - f[i], t[i] + f[i]));
    sort(ALL(vp));
    for(int i = 0; i &lt; n; i++) v.pb(vp[i].second);
    reverse(ALL(v));
    //PV(ALL(v));
    cout &lt;&lt; LIS1(v) &lt;&lt; endl;
    //P2(LIS1(v), LIS(v));
    //assert(LIS1(v) == LIS(v));
    return 0;
}
</code></pre>

<p><strong>Problem Tester Code</strong>:</p>

<pre><code>#include &lt;cstdio&gt;
#include &lt;algorithm&gt;
#include &lt;set&gt;

using namespace std;

pair&lt;int,int&gt; a[100005];
set&lt;int&gt; have;

int main() {
int n;
    scanf("%d",&amp;n);
    for (int i = 0; i &lt; n; ++i)  {
        int x,y;
        scanf("%d%d",&amp;x,&amp;y);
        a[i] = make_pair(x + y,x - y);
    }
    sort(a, a + n);
    for (int i = 0; i &lt; n; ++i) {
        //printf("%d %d\n",a[i].first,a[i].second);

        set&lt;int&gt;::iterator t =  have.lower_bound(a[i].second);

        if ((t != have.end()) &amp;&amp; (*t == a[i].second)) {
            continue;
        }
        if (t != have.begin()) {
            have.erase(--t);

        }
        have.insert(a[i].second);
    }
    printf("%d\n",have.size());
    return 0;
}






#include &lt;cmath&gt;
#include &lt;cstdio&gt;
#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;utility&gt;
using namespace std;

#define Pair pair&lt;int, int&gt;

#define MAX 100000

Pair v[MAX];
int a[MAX];
int dp[MAX + 1];

int main() {
    int n;
    scanf("%d", &amp;n);
    for (int i = 0; i &lt; n; i++) {
        int x, y;
        scanf("%d%d", &amp;x, &amp;y);
        v[i] = make_pair(x - y, x + y);
    }
    sort(v, v + n);
    for (int i = 0; i &lt; n; i++)
        a[i] = v[n - i - 1].second;
    int r = 1;
    dp[1] = a[0];
    for (int i = 1; i &lt; n; i++) {
        int low = 1, high = r;
        if (a[i] &lt;= dp[1]) {
            dp[1] = a[i];
            continue;
        }
        while (low &lt; high) {
            int mid = (low + high + 1) / 2;
            if (dp[mid] &gt;= a[i])
                high = mid - 1;
            else
                low = mid;
        }
        if (low == r) r++;
        dp[low + 1] = a[i];
    }
    cout &lt;&lt; r &lt;&lt; endl;
    return 0;
}
</code></pre>

Reference solution (C++):
###C++  
```cpp  

#include <cstdio>
#include <algorithm>
#include <set>
    
using namespace std;
    
pair<int,int> a[100005];
set<int> have;
    
int main() {
int n;
    scanf("%d",&n);
    for (int i = 0; i < n; ++i)  {
        int x,y;
        scanf("%d%d",&x,&y);
        a[i] = make_pair(x + y,x - y);
    }
    sort(a, a + n);
    for (int i = 0; i < n; ++i) {
        //printf("%d %d\n",a[i].first,a[i].second);
        
        set<int>::iterator t =  have.lower_bound(a[i].second);
        
        if ((t != have.end()) && (*t == a[i].second)) {
            continue;
        }
        if (t != have.begin()) {
            have.erase(--t);
           
        }
        have.insert(a[i].second);
    }
    printf("%d\n",have.size());
    return 0;
}
    





#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <utility>
using namespace std;
    
#define Pair pair<int, int>
    
#define MAX 100000
    
Pair v[MAX];
int a[MAX];
int dp[MAX + 1];
    
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        v[i] = make_pair(x - y, x + y);
    }
    sort(v, v + n);
    for (int i = 0; i < n; i++)
        a[i] = v[n - i - 1].second;
    int r = 1;
    dp[1] = a[0];
    for (int i = 1; i < n; i++) {
        int low = 1, high = r;
        if (a[i] <= dp[1]) {
            dp[1] = a[i];
            continue;
        }
        while (low < high) {
            int mid = (low + high + 1) / 2;
            if (dp[mid] >= a[i])
                high = mid - 1;
            else
                low = mid;
        }
        if (low == r) r++;
        dp[low + 1] = a[i];
    }
    cout << r << endl;
    return 0;
}
```