In this HackerEarth Mr. Sinister and his World problem solution, It is a very bad time for human race, as powerful mutant Mr. Sinister has taken control of the world. He is killing a lot of people. The world is one dimensional and at most one man can stay at one point of the world. The points are numbered from (1,0) to (I N F, 0) where I N F denotes infinity.

As Sinister is killing humans, he wants to know the maximum distance between any two adjacent humans in the world. But a human can come or leave the world (goes to another planet) at a time. So, there will be three types of queries of the following form.

1 X - A human comes and occupies co-ordinate (X,0). It is guaranteed that before this query, there will be no human at the given point.

2 - You have to find out the maximum distance between any two adjacent humans and the position of these two humans. If there is a tie in the maximum adjacent distances, then print the one which has maximum X coordinates.


HackerEarth Mr. Sinister and his World problem solution


HackerEarth Mr. Sinister and his World problem solution.

#include <bits/stdc++.h>

#define FOR(i, s, e) for(int i=s; i<e; i++)
#define loop(i, n) for(int i=0; i<n; i++)
#define CIN   ios_base::sync_with_stdio(0); cin.tie(0)
#define getint(n) scanf("%d", &n)
#define pb(a) push_back(a)
#define ll long long int
#define ull unsigned long long int
#define dd double
#define SZ(a) int(a.size())
#define read() freopen("input.txt", "r", stdin)
#define write() freopen("output.txt", "w", stdout)
#define mem(a, v) memset(a, v, sizeof(a))
#define all(v) v.begin(), v.end()
#define pi acos(-1.0)
#define pf printf
#define sf scanf
#define mp make_pair
#define paii pair<int, int>
#define padd pair<dd, dd>
#define pall pair<ll, ll>
#define fr first
#define sc second
#define CASE(n) printf("Case %d:\n",++n)
#define CASE_COUT cout<<"Case "<<++cas<<": "
#define inf 1000000000
#define EPS 1e-9
#define Harmonic(n) (0.577215664901532+log(n)+(1/(2*n)))     ///Use Only for large n
#define mx 100005

using namespace std;

int SET(int n,int pos){ return n=n | (1<<pos);}
int RESET(int n,int pos){ return n=n & ~(1<<pos);}
int CHECK(int n,int pos){ return (bool) (n & (1<<pos));}

int str2int(string s) {
    stringstream ss(s);
    int x;
    ss >> x;
    return x;
}

string int2str(int a) {
    stringstream ss;
    ss << a;
    string str = ss.str();
    return str;
}

string char2str(char a) {
    stringstream ss;
    ss << a;
    string str = ss.str();
    return str;
}

ll bigMod(ll n,ll power,ll MOD)
{
    if(power==0)
        return 1;
    if(power%2==0)
    {
        ll ret=bigMod(n,power/2,MOD);
        return ((ret%MOD)*(ret%MOD))%MOD;
    }
    else return ((n%MOD)*(bigMod(n,power-1,MOD)%MOD))%MOD;
}

ll modInverse(ll n,ll MOD)
{
    return bigMod(n,MOD-2,MOD);
}

int POW(int x, int y)
{
    int res= 1;
    for ( ; y ; ) {
        if ( (y&1) ) {
            res*= x;
        }
        x*=x;
        y>>=1;
    }
    return res;
}

int inverse(int x)
{
    dd p=((dd)1.0)/x;
    return (p)+EPS;
}

int gcd(int a, int b)
{
    while(b) b^=a^=b^=a%=b;
    return a;
}

int nC2(int n)
{
    return n*(n-1)/2;
}

ll MOD(ll n,ll mod)
{
    if(n>=0)
        return n%mod;
    else if(-n==mod)
        return 0;
    else
        return mod+(n%mod);
}

int n,tree[1000005],data[100005];

set< pair< int, paii > >sata;       ///This will hold the distance and co-ordinate


void update(int i,int val)          ///Update the BIT
{
    while(i<=1000000)
    {
        tree[i]+=val;
        i+=i & (-i);
    }
}

int query(int i)                    ///Query
{
    int sum=0;
    while(i>0)
    {
        sum+=tree[i];
        i-=i & (-i);
    }
    return sum;
}

int leftIndex(int id)               ///Find out the nearest co-ordinate left side of the given point
{
    if(query(id)==0) return -1;     ///If there is no point in the left  return -1
    int lo=1;
    int hi=id;
    int mid=(lo+hi)/2;
    int ans;
    while(lo<=hi)
    {
        int pp=query(id)-query(mid-1);
        if(pp>=1)
        {
            ans=mid;
            lo=mid+1;
        }
        else
            hi=mid-1;
        mid=(lo+hi)/2;
    }
    return ans;
}


int rightIndex(int id)              ///Find out the nearest index right side of the given point
{
    if(query(1000000)-query(id-1)==0) return -1;    ///If there is no point in the right  return -1
    int lo=id;
    int hi=1000000;
    int mid=(lo+hi)/2;
    int ans;
    while(lo<=hi)
    {
        int pp=query(mid)-query(id-1);
        if(pp>=1)
        {
            hi=mid-1;
            ans=mid;
        }
        else
            lo=mid+1;
        mid=(lo+hi)/2;
    }
    return ans;
}

int main()
{
    int t,cas=0;
    cin>>t;
    assert(t>=1 && t<=5);
    while(t--)
    {
        mem(tree,0);
        sata.clear();
        cin>>n;
        assert(n>=2 && n<=100000);
        loop(i,n)
        {
            int p;
            cin>>p;
            assert(p>=1 && p<=1000000);
            update(p,1);                ///Update the new point on BIT
            data[i]=p;
        }
        sort(data,data+n);
        for(int i=0;i<n-1;i++)
        {
            sata.insert(mp(data[i+1]-data[i],mp(data[i],data[i+1])));   /// put all the distance and their co-ordinate. It will be sorted
        }
        int q;
        cin>>q;
        assert(q>=1 && q<=100000);
        CASE(cas);
        while(q--)
        {
            int type;
            cin>>type;
            if(type==1)             ///Insert
            {
                int x;
                cin>>x;
                assert(x>=1 && x<=1000000);
                int index1=leftIndex(x);
                int index2=rightIndex(x);
                if(index1!=-1 && index2!=-1) 
                {
                    sata.erase(mp(index2-index1,mp(index1,index2)));
                    sata.insert(mp(x-index1,mp(index1,x)));
                    sata.insert(mp(index2-x,mp(x,index2)));
                }
                else if(index1==-1 && index2!=-1)
                {
                    sata.insert(mp(index2-x,mp(x,index2)));
                }
                else if(index1!=-1 && index2==-1)
                {
                    sata.insert(mp(x-index1,mp(index1,x)));
                }
                update(x,1);
            }
            else if(type==3)        ///Delete
            {
                int x;
                cin>>x;
                assert(x>=1 && x<=1000000);
                int index1=leftIndex(x-1);
                int index2=rightIndex(x+1);
                if(index1!=-1 && index2!=-1)            ///Remove the previous point adjacent to the given point and put new
                {
                    sata.erase(mp(x-index1,mp(index1,x)));
                    sata.erase(mp(index2-x,mp(x,index2)));
                    sata.insert(mp(index2-index1,mp(index1,index2)));
                }
                else if(index1==-1 && index2!=-1)
                {
                    sata.erase(mp(index2-x,mp(x,index2)));
                }
                else if(index1!=-1 && index2==-1)
                {
                    sata.erase(mp(x-index1,mp(index1,x)));
                }
                update(x,-1);
            }
            else
            {
                auto it=sata.rbegin();
                int lef=it->sc.fr; 
                int rt=it->sc.sc;
                int ans=rt-lef;
                pf("%d %d %d\n",ans,lef,rt);
            }
        }

    }
    return  0;

}

Second solution

#include <bits/stdc++.h>
#define MAX 1000005
#define INF 1000000000

using namespace std;

int A[MAX];
bool vis[MAX];
set < pair <int, int> > s;

struct node {
    int mx;
    int mn;
    node() { }
    node(int mx, int mn) {
        this->mx = mx, this->mn = mn;
    }
}tree[4*MAX];

node combine(node a, node b)
{
    return node(max(a.mx,b.mx), min(a.mn, b.mn));    
}

void build(int where, int left, int right)
{
    if ( left > right ) return;
    if ( left == right ) {
        if ( vis[left] ) tree[where].mx = tree[where].mn = left;
        else tree[where].mx = 0, tree[where].mn = INF;
        return;
    }
    int mid = (left + right)/2;
    build(where*2, left, mid);
    build(where*2 + 1, mid + 1, right);
    tree[where] = combine(tree[where*2], tree[where*2 + 1]);
}

void update(int where, int left, int right, int idx)
{
    if ( left > right || left > idx || right < idx ) return;
    if ( left == right ) {
        if ( vis[left] ) tree[where].mx = tree[where].mn = left;
        else tree[where].mx = 0, tree[where].mn = INF;
        return;
    }
    int mid = (left + right)/2;
    update(where*2, left, mid, idx);
    update(where*2 + 1, mid + 1, right, idx);
    tree[where] = combine(tree[where*2], tree[where*2 + 1]);
}

node query(int where, int left, int right, int i, int j)
{
    if ( left > right || left > j || right < i ) return node(0, INF);
    if ( left >= i && right <= j ) return tree[where];
    int mid = (left + right)/2;
    return combine(query(where*2, left, mid, i, j), query(where*2 + 1, mid + 1, right, i, j));
}

void add(int x)
{
    node ryt = query(1, 1, 1000000, x + 1, 1000000);
    node lft = query(1, 1, 1000000, 1, x - 1);
    
    int right_val = ryt.mn;
    int left_val = lft.mx;
    
    if ( right_val == INF ) {
        s.insert(make_pair(x - left_val, left_val));
    }
    else if ( right_val == tree[1].mn ) {
        s.insert(make_pair(right_val - x, x));
    }
    else {
        s.erase(make_pair(right_val - left_val, left_val));
        s.insert(make_pair(x - left_val, left_val));
        s.insert(make_pair(right_val - x, x));
    }
    update(1, 1, 1000000, x);
}

void _remove(int x)
{
    node ryt = query(1, 1, 1000000, x + 1, 1000000);
    node lft = query(1, 1, 1000000, 1, x - 1);
    
    int right_val = ryt.mn;
    int left_val = lft.mx;
    
    if ( right_val == INF ) {
        s.erase(make_pair(x - left_val, left_val));
    }
    else {
        if ( left_val == 0 ) {
            s.erase(make_pair(right_val - x, x));
        }
        else {
            s.erase(make_pair(x - left_val, left_val));
            s.erase(make_pair(right_val - x, x));
            s.insert(make_pair(right_val - left_val, left_val));
        }
    }
    update(1, 1, 1000000, x);
}

int main()
{
    int t, n, x, q, type, tot;
    
    cin >> t;
    assert(t >= 1 && t <= 3);
    
    for ( int tc = 1; tc <= t; tc++ ) {
        
        cin >> n;
        assert(n >= 2 && n <= 100000);
        
        tot = n;

        for ( int i = 1; i <= 1000000; i++ ) vis[i] = false;
        
        for ( int i = 0; i < n; i++ ) {
            cin >> A[i];
            assert(A[i] >= 1 && A[i] <= 1000000);
            vis[A[i]] = true;
        }
        
        build(1, 1, 1000000);
        
        sort(A, A + n);
        
        s.clear();
        
        for ( int i = 1; i < n; i++ ) {
            assert(A[i] != A[i - 1]);
            s.insert(make_pair(A[i] - A[i - 1], A[i - 1]));
        }
        
        cout << "Case " << tc << ":" << endl;
        cin >> q;
        assert(q >= 1 && q <= 100000);
        
        while ( q-- ) {
            
            cin >> type;
            assert(type >= 1 && type <= 3);
            
            if ( type == 1 ) {
                cin >> x;
                assert(x >= 1 && x <= 1000000);
                assert(vis[x] == false);
                tot++;
                vis[x] = true;
                add(x);
            }
            else if ( type == 2 ) {
                set < pair <int, int> > :: reverse_iterator it = s.rbegin();
                cout << it->first << " " << it->second << " " << it->first + it->second << endl;
            }
            else {
                cin >> x;
                assert(tot >= 2);
                assert(x >= 1 && x <= 1000000);
                assert(vis[x] == true);
                tot--;
                vis[x] = false;
                _remove(x);
            }
            
        }
        
    }
}