Wednesday, 4 November 2015

KQUERYO - K-Query Online(vector in segtree , merege sort )

KQUERYO - K-Query Online

no tags 

Given a sequence of n numbers a1, a2, ..., an and a number of k- queries. A k-query is a triple (i, j, k) (1 ≤ i ≤ j ≤ n). For each k-query (i, j, k), you have to return the number of elements greater than k in the subsequence ai, ai+1, ..., aj.

Input

  • Line 1: n (1 ≤ n ≤ 30000).
  • Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 109).
  • Line 3: q (1 ≤ q ≤ 200000), the number of k- queries.
  • In the next q lines, each line contains 3 numbers a, b, c representing a k-query. You should do the following:
  • i = a xor last_ans
  • j = b xor last_ans
  • k = c xor last_ans
  • After that 1 ≤ i ≤ j ≤ n, 1 ≤ k ≤ 109  holds. 
Where last_ans = the answer to the last query (for the first query it's 0).

Output

  • For each k-query (i, j, k), print the number of elements greater than k in the subsequence ai, ai+1, ..., aj in a single line.

Example

Input:
6
6 8 9 3 5 1 9 5 2 3 5 3 3 7 0 0 11 0 0 2 3 7 4
3 3 26 8 9 3 5 1 9 5 2 3 5 3 3 7 0 0 11 0 0 2 3 7 4
0 5
Output:
1
1
0
0
2
--------------------------------------editorial---------------------------------------------------
In this type of segment tree, for each node we have a vector (we may also have some other variables beside this) .
Example : Online approach for problem KQUERYO (I added this problem as the online version of KQUERY):
It will be nice if for each node, with interval [l, r) such that i ≤ l ≤ r ≤ j + 1 and this interval is maximal (it's parent's interval is not in the interval [i, j + 1) ), we can count the answer.
For that propose, we can keep all elements of al, al + 1, ..., ar in increasing order and use binary search for counting. So, memory will beO(n.log(n)) (each element is in O(log(n)) nodes ). We keep this sorted elements in verctor v[i] for i - th node. Also, we don't need to run sort on all node's vectors, for node i, we can merge v[2 * i] and v[2 * id + 1] (like merge sort) .
So, build function is like below :
void build(int id = 1,int l = 0,int r = n){
 if(r - l < 2){
  v[id].push_back(a[l]);
  return ;
 }
 int mid = (l+r)/2;
 build(2 * id, l, mid);
 build(2*id+1, mid, r);
 merge(v[2 * id].begin(), v[2 * id].end(), v[2 * id + 1].begin(), v[2 * id + 1].end(), back_inserter(v[id])); // read more about back_inserter in http://www.cplusplus.com/reference/iterator/back_inserter/
}
And function for solving queries :
int cnt(int x,int y,int k,int id = 1,int l = 0,int r  = n){// solve the query (x,y-1,k)
 if(x >= r or l >= y) return 0;
 if(x <= l && r <= n)
  return v[id].size() - (upper_bound(v[id].begin(), v[id].end(), k) - v[id].begin());
 int mid = (l+r)/2;
 return cnt(x, y, k, 2 * id, l, mid) +
     cnt(x, y, k, 2*id+1, mid, r) ;
}
--------------------------------code----------------------------------------------
#include<iostream>
using namespace std;
#include<bits/stdc++.h>
struct node
 {
  vector<int> v;
  
 } seg[300000];
int arr[300000];
 int val,qs,qe;
 void build(int index,int start,int end)
  {
   //cout<<start<<" "<<end<<endl;
   if(start==end)
    {
     seg[index].v.push_back(arr[start]);
     return ;
    }
    else if(start>end) return;
    int mid=(start+end)/2;
     build(2*index,start,mid);
     build(2*index+1,mid+1,end);
     
     int len1=seg[2*index].v.size();
     int len2=seg[2*index+1].v.size();
     int p=0,q=0;
     while(p!=len1 && q!=len2)
      {
         if(seg[2*index].v[p]<=seg[2*index+1].v[q])
          {
           seg[index].v.push_back(seg[2*index].v[p]);
           p++;
    }
    else
    {
     seg[index].v.push_back(seg[2*index+1].v[q]);
           q++;
    }
   }
   while(p<len1)
    {
     seg[index].v.push_back(seg[2*index].v[p]);
           p++;
    }
     while(q<len2)
    {
     seg[index].v.push_back(seg[2*index+1].v[q]);
           q++;
    }
    
 //   cout<<"vector of index "<<index<<endl;
 //   for(int i=0;i<seg[index].v.size();i++)
     {
  //     cout<<seg[index].v[i]<<" ";;
     }
  //    cout<<endl;
    
  
 }
 
 int query(int index,int start,int end)
  {
   
     if(start>end || start>qe || end<qs) return 0;
      if(qs<=start && qe>=end)
      {
       int re=0;
       if(lower_bound(seg[index].v.begin(),seg[index].v.end(),val+1)!=seg[index].v.end())
       {
   if(*lower_bound(seg[index].v.begin(),seg[index].v.end(),val+1)>val)
   re=lower_bound(seg[index].v.begin(),seg[index].v.end(),val+1)-seg[index].v.end();
   
}
        //  cout<<" from index "<<index<<" return "<<-re<<" se  "<<start<<"  "<<end<<endl;
           return -re;
           
             
   }
   int mid=(start+end)/2;
   
   int p1=query(2*index,start,mid);
   int p2=query(2*index+1,mid+1,end);
   return p1+p2;
  }
 
 int main()
  {
   ios_base::sync_with_stdio(0);
   cin.tie(0);

int n;
 cin>>n;
 for(int i=1;i<=n;i++)
  {
    cin>>arr[i];
  }
  build(1,1,n);
  int q;
   int ans=0;
   cin>>q;
   while(q--)
    {
      cin>>qs>>qe>>val;
      //qs-=1;
      //qe-=1;
      qs ^=ans;
      qe ^= ans;
      val ^= ans;
    //  cout<<qs<<"  "<<qe<<"  desdf "<<val<<endl;
      
      ans=query(1,1,n);
      cout<<ans<<endl;
      
 }
  }

**KQUERY - K-query(offline + segment tree)

KQUERY - K-query


Given a sequence of n numbers a1, a2, ..., an and a number of k- queries. A k-query is a triple (i, j, k) (1 ≤ i ≤ j ≤ n). For each k-query (i, j, k), you have to return the number of elements greater than k in the subsequence ai, ai+1, ..., aj.

Input

  • Line 1: n (1 ≤ n ≤ 30000).
  • Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 109).
  • Line 3: q (1 ≤ q ≤ 200000), the number of k- queries.
  • In the next q lines, each line contains 3 numbers i, j, k representing a k-query (1 ≤ i ≤ j ≤ n, 1 ≤ k ≤ 109).

Output

  • For each k-query (i, j, k), print the number of elements greater than k in the subsequence ai, ai+1, ..., aj in a single line.

Example

Input
5
5 1 2 3 4
3
2 4 1
4 4 4
1 5 2 

Output
2
0
3 
--------------------------------------------editorial-------------------------------------------------
Imagine we have an array b1, b2, ..., bn which,  and bi = 1 if an only if ai > k, then we can easily answer the query (i, j, k) inO(log(n)) using a simple segment tree (answer is bi + bi + 1 + ... + bj ).
We can do this ! We can answer the queries offline.
First of all, read all the queries and save them somewhere, then sort them in increasing order of k and also the array a in increasing order (compute the permutation p1, p2, ..., pn where ap1 ≤ ap2 ≤ ... ≤ apn)
At first we'll set all array b to 1 and we will set all of them to 0 one by one.
Consider after sorting the queries in increasing order of their k, we have a permutation w1, w2, ..., wq (of 1, 2, ..., q) wherekw1 ≤ kw2 ≤ kw2 ≤ ... ≤ kwq (we keep the answer to the i - th query in ansi .
Pseudo code : (all 0-based)
po = 0
for j = 0 to q-1
 while po < n and a[p[po]] <= k[w[j]]
  b[p[po]] = 0, po = po + 1
So, build function would be like this (s[x] is the sum of b in the interval of node x) :
void build(int id = 1,int l = 0,int r = n){
 if(r - l < 2){
  s[id] = 1;
  return ;
 }
 int mid = (l+r)/2;
 build(2 * id, l, mid);
 build(2 * id + 1, mid, r);
 s[id] = s[2 * id] + s[2 * id + 1];
}
et An update function for when we want to st b[p[po]] = 0 to update the segment tree:
void update(int p,int id = 1,int l = 0,int r = n){
 if(r - l < 2){
  s[id] = 0;
  return ;
 }
 int mid = (l+r)/2;
 if(p < mid)
  update(p, 2 * id, l, mid);
 else
  update(p, 2 * id + 1, mid, r);
 s[id] = s[2 * id] + s[2 * id + 1];
}
Finally, a function for sum of an interval
int sum(int x,int y,int id = 1,int l = 0,int r = n){// [x, y)
 if(x >= r or l >= y) return 0;// [x, y) intersection [l,r) = empty
 if(x <= l && r <= y) // [l,r) is a subset of [x,y)
  return s[id];
 int mid = (l + r)/2;
 return sum(x, y, id * 2, l, mid) +
        sum(x, y, id*2+1, mid, r) ;
}
So, in main function instead of that pseudo code, we will use this :
build();
int po = 0;
for(int y = 0;y < q;++ y){
 int x = w[y];
 while(po < n && a[p[po]] <= k[x])
  update(p[po ++]);
 ans[x] = sum(i[x], j[x] + 1); // the interval [i[x], j[x] + 1)
}
-------------------------------------------code--------------------------------------
#include<iostream>
#include<string.h>
#include<bits/stdc++.h>
 int nn[30005];
int arr[30005],seg[100000];
using namespace std;

vector<pair<int,int> > v;


int ans[200005];
struct node
 {
  int k,l,r,qn;
 } vv[200005];
 
 
 int read_int(){
 char r;
 bool start=false,neg=false;
 int ret=0;
 while(true){
  r=getchar();
  if((r-'0'<0 || r-'0'>9) && r!='-' && !start){
   continue;
  }
  if((r-'0'<0 || r-'0'>9) && r!='-' && start){
   break;
  }
  if(start)ret*=10;
  start=true;
  if(r=='-')neg=true;
  else ret+=r-'0';
 }
 if(!neg)
  return ret;
 else
  return -ret;
}

#define inf 100000001



bool compare(node n1,node n2)
 {
  if(n1.k>n2.k) return false;
  else return true;
 }
 
 
 
 
 int ups,upe,qs,qe;//qs = query start index , qe= query end index   
 int val;// ups = update start index , upe =update end index
 
 
int qry(int index,int start,int end)
  {
     
       
         if(start>end || end<qs || start>qe)
       {
        return 0;
       }
        if(start>=qs && end<=qe)
         {
          return  seg[index];
          
         }
        int q1=qry(2*index,start,(start+end)/2);
          int q2=qry(2*index+1,((start+end)/2)+1,end);
         return q1+q2;
   
  }
  
  void build(int index,int start,int end)
   {
  
    
    
   if(start==end)
    {
     seg[index]=1;
     return;
 }

    
     build(2*index,start,(start+end)/2);
     build(2*index+1,((start+end)/2)+1,end);
     
     seg[index]=seg[2*index]+seg[2*index+1];
   //  cout<<" index        "<<index<<" val "<<seg[index]<<endl;
   }
   
   
   
void update(int index,int start,int end)
{
// cout<<"update "<<start<<" "<<end<<endl;
   if(start>end || start>upe || end<ups) return ;// if(range in complitly out of range sooo need not to update ;;;;)
   if(start==end && start==ups)
    {
    // cout<<" reach "<<index<<endl;
     seg[index]=0;
     return ;
 }
 //else if(start==end) return ;
    
     update(2*index,start,(start+end)/2);
     update(2*index+1,((start+end)/2)+1,end);
     
     seg[index]=seg[2*index]+seg[2*index+1];
  
 }
 
 

int main()
 {
 
       
      
        int n,q;
       n=read_int();
        for(int i=0;i<n;i++) 
  {
   int a;
   a=read_int();
    v.push_back(make_pair(a,i));
     arr[i]=1;
  }
       
   //cout<<"build call "<<endl;
   build(1,0,n-1);
  // cout<<"build return "<<endl;
   
   sort(v.begin(),v.end());
   
        
     for(int i=0;i<n;i++) nn[i]=(v[i].first);
  //   cout<<" copy done "<<endl;
   q=read_int();
    
   for(int i=0;i<q;i++)
     {
      
      int l,r,k;
      // cin>>l>>r>>k;
      l=read_int();
      r=read_int();
      k=read_int();
       vv[i].l=l;
       vv[i].r=r;
       vv[i].k=k;
       vv[i].qn=i;
     }
   //  cout<<" qinp done "<<endl;
     sort(vv,vv+q,compare);
     
    // cout<<" after sorting status of the query "<<endl;
     
     for(int i=0;i<q;i++)
      {
       int l,r,k,qn;
       k=vv[i].k;
       l=vv[i].l;
       r=vv[i].r;
       qn=vv[i].qn;
       
    //  cout<<" l "<<vv[i].l<<" r "<<vv[i].r<<" k "<<vv[i].k<<" "<<vv[i].qn<<endl;
      // vector<int > :: iterator it;
      
       
      int *it=lower_bound(nn,nn+n,k+1);
      if(*it>k) it--;
       int pos=it-nn;
       if(pos==n)pos--;
     //cout<<"pos in sorted array is for "<<k<<" is "<<pos<<endl;
       for(int j=pos;j>=0;j--)
        {
      //      cout<<" updating "<<j<<endl;
         if(nn[j]==0) break;
         else
         {
          int place=v[j].second;
         // v[j].first=0;
              nn[j]=0;
          arr[place]=0;
          ups=place;
          upe=place;
              //  cout<<"index of update "<<place<<endl;
          update(1,0,n-1);
          
      }
     }
       qs=l-1;
       qe=r-1;
       ans[qn]=qry(1,0,n-1);
   }
   for(int i=0;i<q;i++) printf("%d\n",ans[i]);
        
     
      
  return 0;
 }
------------------------------------ direct online code is in the next post kqueryo----

Tuesday, 3 November 2015