In this HackerEarth Number of Balloons problem solution, You have arranged balloons in a linear order. Every balloon is colored and the ith balloon's color is represented by Ci. Here, the color of balloons is depicted with numbers. 

The number k is not a suitable number, therefore you decide to use it for the less number of times. You do not contain any range of ballons in which a color repeats exactly k times. If the displayed balloons are numbered from b0,b1,b2,...,bn-1, then the range of balloons from l to r is bl,b1+1,bl+2,...br.

You are provided with some specific ranges and your task is to determine the number of colors that get repeated for exactly k times in each range that is provided.


HackerEarth Number of Balloons problem solution


HackerEarth Number of Balloons problem solution.

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

using namespace std;
const int maxn=1e5+10;
int a[maxn],n,seg[3][20][maxn],mk[maxn],b[maxn];
map<int,vector<int> > mark;

void pre(){
  for(int i=1;i<=n;i++){
    mark[a[i]].push_back(i);
  }
}

struct segment{
  int ans=0,num=0;
  map<int,int> mk;
  segment(int x1,int x2){
    num=x2;
    for(int i=1;i<=n;i++)
      b[i]=0;
    for(int i=1;i<=n;i++)
      if(!mk[a[i]]){
    mk[a[i]]=1;
    for(int j=0;j<mark[a[i]].size();j++)
      if(j>=x1)
        b[mark[a[i]][j]]=mark[a[i]][j-x1];
      else
        b[mark[a[i]][j]]=-1;
      }
    make_seg(1,n,1);
  }
  
  void make_seg(int l,int r,int len)
  {
    if(l==r){
      seg[num][len][l]=b[l];
      return ;
    }
    int mid=(l+r)/2;
    make_seg(l,mid,len+1);
    make_seg(mid+1,r,len+1);
    merge(seg[num][len+1]+l,seg[num][len+1]+mid+1,seg[num][len+1]+mid+1,seg[num][len+1]+r+1,seg[num][len]+l);
  }

  int bs(int l,int r,int k,int len)
  {
    if(l==r){
      if(seg[num][len][l]>=k)
    return 0;
      return l;
    }
    int mid=(l+r+1)/2;
    if(seg[num][len][mid]<k)
      return bs(mid,r,k,len);
    else
      return bs(l,mid-1,k,len);
  }

  void ans_seg(int l,int r,int s,int f,int len)
  {
    if(f<l || r<s)
      return;
    if(s<=l && r<=f){
      int x=bs(l,r,s,len);
      if(x!=0)
    ans+=x-l+1;
      return;
    }
    int mid=(l+r)/2;
    ans_seg(l,mid,s,f,len+1);
    ans_seg(mid+1,r,s,f,len+1);
  }

};

int main()
{
  int k,q;
  cin>>n>>k>>q;
  for(int i=1;i<=n;i++)cin>>a[i];
  pre();
  segment a(k+1,0);
  segment b(k,1);
  segment c(k-1,2);
  int ans=0;
  while(q--){
    int l,r;
    cin>>l>>r;
    l=(l+ans)%n;
    r=(r+ans)%n;
    l++;
    r++;
    if(r<l)
      swap(l,r);
    a.ans_seg(1,n,l,r,1);
    b.ans_seg(1,n,l,r,1);
    c.ans_seg(1,n,l,r,1);
    ans=(b.ans-c.ans)-(a.ans-b.ans);
    cout<<ans<<endl;
    a.ans=0;b.ans=0;c.ans=0;
  }
}

Second solution

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

namespace segment{
    const int maxn = 1e7; // TODO
    int eof = 1;
    int L[maxn], R[maxn], seg[maxn];
    
    int add(int v, int x, int root, int st = 0, int en = n){
    assert(eof<maxn);
    
    seg[eof] = seg[root] + x;
    L[eof] = L[root];
    R[eof] = R[root];
    root = eof++;
    
    if(en - st < 2)
        return root;
    int mid = (st + en) >> 1;
    if(v < mid)
        L[root] = add(v, x, L[root], st, mid);
    else
        R[root] = add(v, x, R[root], mid, en);
    return root;
    }

    int get(int l, int r, int root, int st = 0, int en = n){
    if(l <= st && en <= r)
        return seg[root];
    if(r <= st || en <= l)
        return 0;
    int mid = (st + en) >> 1;
    return get(l, r, L[root], st, mid) +
        get   (l, r, R[root], mid, en);
    }
}

const int maxn = 1e5 + 10;
int k, q, ar[maxn];
int l[maxn], r[maxn];

void init(){
    cin >> n >> k >> q;
    vector<int> vc;
    for(int i = 0; i < n; i++)
    cin >> ar[i], vc.push_back(ar[i]);
    sort(vc.begin(), vc.end());
    vc.resize(unique(vc.begin(), vc.end()) - vc.begin());
    for(int i = 0; i < n; i++)
    ar[i] = lower_bound(vc.begin(), vc.end(), ar[i]) - vc.begin();
    for(int i = 0; i < q; i++)
    cin >> l[i] >> r[i];
}

vector<int> vc[maxn];
int root[maxn];

inline void add(const int &v,const int &x,int &node){
    if(vc[v].size() >= k)
    node = segment::add(vc[v][vc[v].size() - k], x, node);
    if(vc[v].size() > k)
    node = segment::add(vc[v][vc[v].size() - k - 1], -x, node);
}

void build(){
    int node = 0;
    for(int i = 0; i < n; i++){
    add(ar[i], -1, node);
    vc[ar[i]].push_back(i);
    add(ar[i], +1, node);
    root[i] = node;
    }
}

int main(){
    init();
    build();
    int ans = 0;
    for(int i = 0; i < q; i++){
    l[i] = (l[i] + ans) % n;
    r[i] = (r[i] + ans) % n;
    if(l[i] > r[i])
        swap(l[i], r[i]);
    ans = segment::get(l[i], r[i] + 1, root[r[i]]);
    cout << ans << '\n';
    }
}