Sunday, 17 April 2016

*****C. Subsequences( seg tree +dp ) no of lis of length k


C. Subsequences
For the given sequence with n different elements find the number of increasing subsequences with k + 1 elements. It is guaranteed that the answer is not greater than 8·1018.
Input
First line contain two integer values n and k (1 ≤ n ≤ 105, 0 ≤ k ≤ 10) — the length of sequence and the number of elements in increasing subsequences.
Next n lines contains one integer ai (1 ≤ ai ≤ n) each — elements of sequence. All values ai are different.
Output
Print one integer — the answer to the problem.
Examples
input
5 2
1
2
3
5
4
output
7
---------------------------------------------------EDITORIAL---------------------------------------------------
//SIMILAR QUESTION   first see this question
//http://gautamsegtree.blogspot.in/2016/02/d-babaei-and-birthday-cake.html

now 

THIS PROBLEM CAN BE SOLVED WITH SEG TREE + DP , 
 CONCEPT 
ITERATE FROM THE ARRAY AND FOR EACH ELEMENT i  
FIND NO OF WAYS OF PLACING THAT NUMBER AT  PACE J (FOR J ROM 1 TO K ) IN THE SEQUENCE WHICH WE WILL  CREATE ,

OBSERVATION ---
FOR PROCESSING NUMBER ARR[I] WE NEED TO COMPUTED ANSWER FOR ALL ARR[J] <ARR[I] AND J<I    BUT ANY ARR[J] >ARR[I] NEED NOT TO COMPUTED FOR PLACING iTH VALUE SO WE CAN SORT THE ARRAY WITH THE  VALUE AND KEEP INDEX OF EACH NUMBER ALSO ..

NOW SUPPOSE WE ARE TRYING TO PLACE iTH NUMBED AT jTH ( j CAN BE 1 TO K )PLACE  OF OUR SEQUENCE THAN WE JUST NEED THE SUM OF ALL POSSIBLE WAY IN WHICH WE CAN PLACE TILL ELEMENTS idx-1 (where idx-1 is the original index of the element arr[i])  AT POSITION j-1  THIS CAN BE COMPUTE USING A RANGE SUM QUERY , 
RANGE SUM QUERY WILL BE DONE  FROM INDEX 0 TO INDEX OF CURRENT NUMBER (actual index in the initial array ) 

WHILE UPDATING SEGMENT TREE  WE HAVE TO UPDATE ITS ANSWER AT INDEX idx (actual index of this number )

SEE IMPLEMENTATION 


------------------------------------------code------------------------------------------------------------------
#include<bits/stdc++.h>
using namespace std;
typedef long long int  lli;
lli arr[600000];
vector<pair<lli,lli> > v;
lli seg[600000][12];
lli dp[600000][12];

void update(int idx,int start,int end,int ups,int upe,int didx,lli val)
 {
  if(start>end || upe<start || ups>end) return ;
  else if(start==end && start==ups)
    {
      seg[idx][didx]=val;
      return ;
  }
  int mid=(start+end)/2;
  update(2*idx,start,mid,ups,ups,didx,val);
  update(2*idx+1,mid+1,end,ups,upe,didx,val);
  seg[idx][didx]=seg[2*idx][didx]+seg[2*idx+1][didx];
 }
 lli  qry(int idx,int start,int end,int qs,int qe,int didx)
 {
  if(start>end || qe<start || qs>end) return 0 ;
  else if(start>=qs && end<=qe)
    {
      return seg[idx][didx];
  }
  int mid=(start+end)/2;
 lli q1= qry(2*idx,start,mid,qs,qe,didx);
 lli q2= qry(2*idx+1,mid+1,end,qs,qe,didx);
   return (q1+q2);
 }
int main()
 {
  int n,k;
   cin>>n>>k;
   for(int i=0;i<n;i++)
     {
     int a; cin>>a;
     v.push_back({a,i});
  }
  sort(v.begin(),v.end());
   
  for(int i=0;i<n;i++)
   {
         int num=v[i].first;
           int idx=v[i].second;
           update(1,0,n-1,idx,idx,1,1);
           dp[i][1]=1;
           //cout<<" query is "<<num<<" idx "<<idx<<endl;
     for(int j=2;j<=k+1;j++)
         {
            //cout<<"placing "<<num<<" at  place "<<j<<" count "<<count<<endl;
    lli count=qry(1,0,n-1,0,idx-1,j-1);
    dp[i][j]=count;
    
    update(1,0,n-1,idx,idx,j,count);   
 }
   }
   
     lli ans=0;
     for(int i=0;i<n;i++)
      {
        ans+=dp[i][k+1];
 }
  cout<<ans<<endl;
 }

No comments:

Post a Comment