Saturday, August 24, 2019

[Toph] Unique Substrings Query

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Unique Substrings Query
Source            : Toph.co
Category          : Data Structure, String
Algorithm         : Suffix Automaton, Binary Indexed Tree, Persistent Segment Tree
Verdict           : Accepted

#include "bits/stdc++.h"
 
using namespace std;
 
#define ll            long long int
#define endl          '\n'
 
static const int maxn = 2e3 + 5;
static const ll mod = 1e9 + 7;
static const int Max = 6e6 + 7;
 
int N = 1000 + 2;
ll Bit[maxn];
 
ll add(ll a, ll b)
{
      a = (a + b);
      return a;
}
 
void bitUpdate(int pos, ll val)
{
      while (pos <= N)
      {
            Bit[pos] = add(Bit[pos], val);
            pos += (pos & -pos);
      }
}
 
void rangeUpdate(int l, int r, ll val)
{
      bitUpdate(l, val);
      bitUpdate(r + 1, -val);
}
 
ll read(int pos)
{
      ll sum = 0;
      while (pos > 0)
      {
            sum = add(sum, Bit[pos]);
            pos -= (pos & -pos);
      }
      return sum;
}
 
struct state
{
      int len, link;
      map <char, int> next;
} st[maxn * 2];
 
int sz, last;
 
void init()
{
      sz = last = 0;
      st[0].len = 0;
      st[0].link = -1;
      st[0].next.clear();
      for (int i = 1; i < maxn * 2; i++)
      {
            st[i].len = 0;
            st[i].link = 0;
            st[i].next.clear();
      }
      ++sz;
}
 
void szExtend(char c)
{
      int l, r;
      int cur = sz++;
      st[cur].len = st[last].len + 1;
      int p;
      for (p = last; p != -1 && !st[p].next.count(c); p = st[p].link)
      {
            st[p].next[c] = cur;
      }
      if (p == -1)
      {
            st[cur].link = 0;
      }
      else
      {
            int q = st[p].next[c];
            if (st[p].len + 1 == st[q].len)
            {
                  st[cur].link = q;
            }
            else
            {
                  int clone = sz++;
                  st[clone].len = st[p].len + 1;
                  st[clone].next = st[q].next;
                  st[clone].link = st[q].link;
                  for ( ; p != -1 && st[p].next[c] == q; p = st[p].link)
                  {
                        st[p].next[c] = clone;
                  }
                  l = st[ st[q].link ].len;
                  r = st[q].len;
                  assert(l+1 <= r);
                  rangeUpdate(l+1, r, -1);
                  st[q].link = st[cur].link = clone;
                  l = st[ st[q].link ].len;
                  r = st[q].len;
                  assert(l+1 <= r);
                  rangeUpdate(l+1, r, 1);
                  l = st[ st[clone].link ].len;
                  r = st[clone].len;
                  assert(l+1 <= r);
                  rangeUpdate(l+1, r, 1);
            }
      }
      l = st[ st[cur].link ].len;
      r = st[cur].len;
      assert(l+1 <= r);
      rangeUpdate(l+1, r, 1);
      last = cur;
}
 
 
struct Node
{
      ll st;
      int lft, rgt;
      Node(ll st = 0, int lft = 0, int rgt = 0) : st(st), lft(lft), rgt(rgt) {}
} Tree[Max];
 
int version[maxn];
int NODES;
//int N = 1000;
 
int update(int root, int a, int b, int pos, ll val)
{
      int newNode = ++NODES;
      Tree[newNode] = Tree[root];
      if (a == b)
      {
            Tree[newNode].st += val;
            return newNode;
      }
      int mid = (a + b) >> 1;
      if (pos <= mid) Tree[newNode].lft = update(Tree[newNode].lft, a, mid, pos, val);
      else Tree[newNode].rgt = update(Tree[newNode].rgt, mid + 1, b, pos, val);
      Tree[newNode].st = Tree[ Tree[newNode].lft ].st + Tree[ Tree[newNode].rgt ].st;
      return newNode;
}
 
ll query(int proot, int root, int a, int b, int i, int j)
{
      if (a > b or a > j or b < i) return 0;
      if (a >= i && b <= j)
      {
            return Tree[root].st - Tree[proot].st;
      }
      int mid = a + b >> 1;
      ll p = query(Tree[proot].lft, Tree[root].lft, a, mid, i, j);
      ll q = query(Tree[proot].rgt, Tree[root].rgt, mid + 1, b, i, j);
      return p + q;
}
 
int originalVersion[maxn];
 
signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.tie(nullptr);
      cout << fixed << setprecision(8);
 
      #ifndef ONLINE_JUDGE
            freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE
 
      int n, m;
      cin >> n >> m;
      string s;
      cin >> s;
      s = "#" + s;
 
      NODES = 0;
      version[0] = 0;
      for (int i = 0; i < maxn; i++) Tree[i] = Node();
 
      int ptr = 0;
      originalVersion[n + 1] = 0;
      init();
      int len = 0;
      for (int i = n; i >= 1; i--)
      {
            szExtend(s[i]);
            ++len;
            ++ptr;
            originalVersion[i] = ptr;
            bool isCreated = 0;
            for (int j = 1; j <= len; j++)
            {
                  ll val = read(j);
                  if (isCreated == 0)
                  {
                        version[ptr] = update(version[ptr - 1], 1, N, j, val);
                        isCreated = 1;
                  }
                  else
                  {
                        version[ptr] = update(version[ptr], 1, N, j, val);
                  }
            }
      }
      while (m--)
      {
            int L, R, P, Q;
            cin >> L >> R >> P >> Q;
            ll ans = query(version[ originalVersion[R + 1] ], version[ originalVersion[L] ], 1, N, P, Q);
            cout << ans << '\n';
      }
}
 
 

Monday, August 19, 2019

[CS Academy] Rectangle Fit

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Rectangle Fit
Source            : CS Academy
Category          : Data Structure, PBDS
Algorithm         : Easy implementation of Compressed 2D Binary Indexed Tree for grid of 
                    binary numbers
Verdict           : Accepted
Algo Link : Compressed 2D Binary Indexed Tree

#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
 
using namespace std;
using namespace __gnu_pbds;
 
#define pii           pair <int, int>
#define piii          pair <pii, int>
#define mk            make_pair
 
template <typename T> using orderset = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
 
static const int maxn = 1e6 + 5;
 
int N = 1000000;
orderset <piii> bit[maxn];
int ptr;
 
void Insert(int x, int y)
{
      for (int i = x; i <= N; i += (i & -i))
      {
            bit[i].insert(mk(mk(y, x), ++ptr));
      }
}
 
void Remove(int x, int y)
{
      for (int i = x; i <= N; i += (i & -i))
      {
            bit[i].erase(mk(mk(y, x), -1));
      }
}
 
int query(int x, int y)
{
      int ans = 0;
      for (int i = x; i > 0; i -= (i & -i))
      {
            ans += bit[i].order_of_key(mk(mk(y + 1, 0), -1));
      }
      return ans;
}
 
signed main()
{
      int n, area;
      scanf("%d %d", &n, &area);
      vector <pii> point;
      for (int i = 1; i <= n; i++)
      {
            int x, y;
            scanf("%d %d", &x, &y);
            point.push_back(mk(x, y));
      }
      sort(point.begin(), point.end());
      for (pii p : point) Insert(p.first, p.second);
      int maxPoints = 0;
      for (int i = 0; i < n; i++)
      {
            int x = point[i].first;
            int y = min(area / x, N);
            int points = query(x, y);
            maxPoints = max(maxPoints, points);
      }
      printf("%d\n", maxPoints);
}
 

Saturday, August 10, 2019

[Toph] Taju Kage Bunshin No Jutsu

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Taju Kage Bunshin No Jutsu
Source            : Toph.CO
Category          : Data Structure
Algorithm         : Persistent Segment Tree
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. static const int maxn = 4e5 + 5;  
  6. static const int Max = 2e7 + 5;  
  7.   
  8. struct Node  
  9. {  
  10.       int st;  
  11.       int lft, rgt;  
  12.       Node(int st = 0, int lft = 0, int rgt = 0) : st(st), lft(lft), rgt(rgt) {}  
  13. } Tree[Max];  
  14.   
  15. int version[maxn];  
  16. int NODES;  
  17. int N = 300000 + 5;  
  18.   
  19. int update(int root, int a, int b, int pos, int val)  
  20. {  
  21.       int newNode = ++NODES;  
  22.       Tree[newNode] = Tree[root];  
  23.       if (a == b)  
  24.       {  
  25.             Tree[newNode].st += val;  
  26.             return newNode;  
  27.       }  
  28.       int mid = (a + b) >> 1;  
  29.       if (pos <= mid) Tree[newNode].lft = update(Tree[newNode].lft, a, mid, pos, val);  
  30.       else Tree[newNode].rgt = update(Tree[newNode].rgt, mid + 1, b, pos, val);  
  31.       Tree[newNode].st = Tree[ Tree[newNode].lft ].st + Tree[ Tree[newNode].rgt ].st;  
  32.       return newNode;  
  33. }  
  34.   
  35. int query(int proot, int root, int a, int b, int k)  
  36. {  
  37.       if (a == b) return a;  
  38.       int mid = a + b >> 1;  
  39.       int sizeLeftChild = Tree[ Tree[root].lft ].st - Tree[ Tree[proot].lft ].st;  
  40.       if (k <= sizeLeftChild) return query(Tree[proot].lft, Tree[root].lft, a, mid, k);  
  41.       else return query(Tree[proot].rgt, Tree[root].rgt, mid + 1, b, k - sizeLeftChild);  
  42. }  
  43.   
  44. void init()  
  45. {  
  46.       NODES = 0;  
  47.       version[0] = 0;  
  48.       for (int i = 0; i < maxn; i++) Tree[i] = Node();  
  49. }  
  50.   
  51. struct Query  
  52. {  
  53.       int type;  
  54.       int v;  
  55.       int l, r, k;  
  56.       Query(int type = 0, int v = 0, int l = 0, int r = 0, int k = 0)  
  57.             : type(type)  
  58.             , v(v)  
  59.             , l(l)  
  60.             , r(r)  
  61.             , k(k) {}  
  62. };  
  63.   
  64. vector <Query> queries;  
  65. vector <int> vec;  
  66. int arr[maxn];  
  67. map <intint> mapper, rmapper;  
  68.   
  69. int main()  
  70. {  
  71.       ios_base::sync_with_stdio(false);  
  72.       cin.tie(nullptr);  
  73.       cout.tie(nullptr);  
  74.   
  75.       #ifndef ONLINE_JUDGE  
  76.             freopen("in.txt""r", stdin);  
  77.       #endif // ONLINE_JUDGE  
  78.   
  79.       int n;  
  80.       cin >> n;  
  81.       for (int i = 1; i <= n; i++)  
  82.       {  
  83.             cin >> arr[i];  
  84.             vec.emplace_back(arr[i]);  
  85.       }  
  86.       int q;  
  87.       cin >> q;  
  88.       for (int i = 1; i <= q; i++)  
  89.       {  
  90.             int type;  
  91.             cin >> type;  
  92.             if (type == 1)  
  93.             {  
  94.                   int v;  
  95.                   cin >> v;  
  96.                   queries.emplace_back(type, v);  
  97.                   vec.emplace_back(v);  
  98.             }  
  99.             else if (type == 2)  
  100.             {  
  101.                   queries.emplace_back(type);  
  102.             }  
  103.             else  
  104.             {  
  105.                   int l, r, k;  
  106.                   cin >> l >> r >> k;  
  107.                   queries.emplace_back(type, 0, l, r, k);  
  108.             }  
  109.       }  
  110.       sort(vec.begin(), vec.end());  
  111.       int ptr = 0;  
  112.       for (int x : vec)  
  113.       {  
  114.             if (mapper.find(x) == mapper.end())  
  115.             {  
  116.                   mapper[x] = ++ptr;  
  117.                   rmapper[ptr] = x;  
  118.             }  
  119.       }  
  120.       init();  
  121.       for (int i = 1; i <= n; i++)  
  122.       {  
  123.             arr[i] = mapper[ arr[i] ];  
  124.             version[i] = update(version[i-1], 1, N, arr[i], 1);  
  125.       }  
  126.       int lastVersion = n;  
  127.       for (Query &it : queries)  
  128.       {  
  129.             if (it.type == 1)  
  130.             {  
  131.                   it.v = mapper[it.v];  
  132.                   int newVersion = lastVersion + 1;  
  133.                   version[newVersion] = update(version[lastVersion], 1, N, it.v, 1);  
  134.                   lastVersion = newVersion;  
  135.             }  
  136.             else if (it.type == 2)  
  137.             {  
  138.                   --lastVersion;  
  139.             }  
  140.             else  
  141.             {  
  142.                   int l = it.l;  
  143.                   int r = it.r;  
  144.                   int k = it.k;  
  145.                   k = (r - l + 1) - k + 1;  
  146.                   int kth = query(version[l-1], version[r], 1, N, k);  
  147.                   cout << rmapper[kth] << endl;  
  148.             }  
  149.       }  
  150. }