Hackerrank: Lexicographically Smaller or Equal Strings

Problem Link : https://www.hackerrank.com/contests/womens-codesprint-4/challenges/lexicographically-smaller-or-equal-strings

Solution Idea:

    This problem is an example of basic merge sort tree problem. Merge Sort tree is a segment tree in which every node contains a vector. In this problem we can store string in every leaf node of segment tree as the size of the string is <=15. And while merging two leaf node we will merge them in sorted order. Now as the vectors of every node in the segment tree is sorted we can apply binary search on segment tree node to get how many string is lexicographically smaller than the given string.

    So after building merge sort tree we can easily answer every query using binary search.

    If you want to learn some wonderful application of segment tree or merge sort tree you can see this article.



#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pii              pair <int,int>
#define pll              pair <long long,long long>
#define sc               scanf
#define pf               printf
#define Pi               2*acos(0.0)
#define ms(a,b)          memset(a, b, sizeof(a))
#define pb(a)            push_back(a)
#define MP               make_pair
#define db               double
#define ll               long long
#define EPS              10E-10
#define ff               first
#define ss               second
#define sqr(x)           (x)*(x)
#define D(x)             cerr<<#x " = "<<(x)<<endl
#define VI               vector <int>
#define DBG              pf("Hi\n")
#define MOD              1000000007
#define CIN              ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define SZ(a)            (int)a.size()
#define sf(a)            scanf("%d",&a)
#define sfl(a)           scanf("%lld",&a)
#define sff(a,b)         scanf("%d %d",&a,&b)
#define sffl(a,b)        scanf("%lld %lld",&a,&b)
#define sfff(a,b,c)      scanf("%d %d %d",&a,&b,&c)
#define sfffl(a,b,c)     scanf("%lld %lld %lld",&a,&b,&c)
#define stlloop(v)       for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define loop(i,n)        for(int i=0;i<n;i++)
#define loop1(i,n)       for(int i=1;i<=n;i++)
#define REP(i,a,b)       for(int i=a;i<b;i++)
#define RREP(i,a,b)      for(int i=a;i>=b;i--)
#define TEST_CASE(t)     for(int z=1;z<=t;z++)
#define PRINT_CASE       printf("Case %d: ",z)
#define LINE_PRINT_CASE  printf("Case %d:\n",z)
#define CASE_PRINT       cout<<"Case "<<z<<": "
#define all(a)           a.begin(),a.end()
#define intlim           2147483648
#define infinity         (1<<28)
#define ull              unsigned long long
#define gcd(a, b)        __gcd(a, b)
#define lcm(a, b)        ((a)*((b)/gcd(a,b)))

using namespace std;

//using namespace __gnu_pbds;
//typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;


/*----------------------Graph Moves----------------*/
//const int fx[]={+1,-1,+0,+0};
//const int fy[]={+0,+0,+1,-1};
//const int fx[]={+0,+0,+1,-1,-1,+1,-1,+1};   // Kings Move
//const int fy[]={-1,+1,+0,+0,+1,+1,-1,-1};  // Kings Move
//const int fx[]={-2, -2, -1, -1,  1,  1,  2,  2};  // Knights Move
//const int fy[]={-1,  1, -2,  2, -2,  2, -1,  1}; // Knights Move
/*------------------------------------------------*/

/*-----------------------Bitmask------------------*/
//int Set(int N,int pos){return N=N | (1<<pos);}
//int reset(int N,int pos){return N= N & ~(1<<pos);}
//bool check(int N,int pos){return (bool)(N & (1<<pos));}
/*------------------------------------------------*/

#define mx 100005

vector<string>tree[3*mx],v;

void init(int n, int b, int e)
{
    if(b==e)
    {
        tree[n].pb(v[b]);
        return;
    }
    int l=n*2,r=l+1,mid=(b+e)/2;
    init(l,b,mid);
    init(r,mid+1,e);
    merge(all(tree[l]),all(tree[r]),back_inserter(tree[n]));
//    cout<<n<<" "<<b<<" "<<e<<endl;
//    for(int i=0;i<SZ(tree[n]);i++)
//        cout<<tree[n][i]<<endl;
//    cout<<"-----------------------------"<<endl;
}


int query(int n, int b, int e, int i, int j, string &str)
{
    if(b>j || e<i) return 0;
    if(b>=i && e<=j)
    {
//        int x=upper_bound(all(tree[n]),str)-tree[n].begin();
//        int y=lower_bound(all(tree[n]),str)-tree[n].begin();
//        int z=x-y;
//        return z;
        return upper_bound(all(tree[n]),str)-tree[n].begin();
    }
    int l=n*2,r=l+1,mid=(b+e)/2;
    int p=query(l,b,mid,i,j,str);
    int q=query(r,mid+1,e,i,j,str);
    return p+q;
}


int main()
{
//    freopen("in.txt","r",stdin);
//	  freopen("out.txt","w",stdout);

    int n;
    sf(n);

    v.pb("");
    char sss[30];

    for(int i=0;i<n;i++)
    {
        scanf(" %s",sss);
        v.pb(string(sss));
    }

    init(1,1,n);

    int q;
    sf(q);
    while(q--)
    {
        int a,b;
        sff(a,b);
        scanf(" %s",sss);

        string str=string(sss);
//        cout<<str<<endl;
        int ans=query(1,1,n,a,b,str);
        printf("%d\n",ans);
    }



    return 0;
}

Advertisements