Thursday, 19 May 2016

*****E. Holes( (SQRT + DP ) NUMBER OF STEP IN WHICH REACH AT SOME INDEX > N )

E. Holes
Little Petya likes to play a lot. Most of all he likes to play a game «Holes». This is a game for one person with following rules:
There are N holes located in a single row and numbered from left to right with numbers from 1 to N. Each hole has it's own power (hole number i has the power ai). If you throw a ball into hole i it will immediately jump to hole i + ai, then it will jump out of it and so on. If there is no hole with such number, the ball will just jump out of the row. On each of the M moves the player can perform one of two actions:
  • Set the power of the hole a to value b.
  • Throw a ball into the hole a and count the number of jumps of a ball before it jump out of the row and also write down the number of the hole from which it jumped out just before leaving the row.
Petya is not good at math, so, as you have already guessed, you are to perform all computations.
Input
The first line contains two integers N and M (1 ≤ N ≤ 1051 ≤ M ≤ 105) — the number of holes in a row and the number of moves. The second line contains N positive integers not exceeding N — initial values of holes power. The following M lines describe moves made by Petya. Each of these line can be one of the two types:
  • 0 a b
  • 1 a
Type 0 means that it is required to set the power of hole a to b, and type 1 means that it is required to throw a ball into the a-th hole. Numbers a and b are positive integers do not exceeding N.
Output
For each move of the type 1 output two space-separated numbers on a separate line — the number of the last hole the ball visited before leaving the row and the number of jumps it made.
Examples
input
8 5
1 1 1 1 1 2 8 2
1 1
0 1 3
1 1
0 3 4
1 2
output
8 7
8 5
7 3

============================EDITORIAL ===================================
THIS PROBLEM CAN BE SOLVED WITH SQRT DECOMPOSITION ,  AND  SOME BASIC CONCEPT OF DYNAMIC PROGRAMMING , 
FIRST OF ALL WE DIVIDE THE ENTIRE HOLES IN TO BLOCKS , EACH BLOCK WILL CONTAIN AT MAX 350 HOLES ,
NOW  WE WILL KEEP TRACK OF 3 THINGS 

1-> NEXT[i] = IF WE ARE CURRENTLY AT SOME INDEX i , SO ITS CURRENT BLOCK WILL BE i/350( SAY IT x) , NEXT[i]  WILL CONTAIN THE  FIRST INDEX IN NEXT BLOCK(x+1)  WHICH   IT  WILL REACH ... IN ITS MOVE ..

2-> COUNT[i]= IF WE ARE AT INDEX i NUMBER OF MOVES REQUIRED TO LEAVE  THE CURRENT BLOCK AND REACH TO THE NEXT BLOCK .. ( ie FORM  BLOCK x TO x+1  )
MEANS NUMBER OF MOVE IN THE SAME BLOCK BEFORE REACHING TO NEXT BLOCK

3->LAST[i] = IF WE ARE AT INDEX i ,   IT WILL CONTAIN THE LAST INDEX( IN THE CURRENT BLOCK )  WHICH COVER WHILE LEAVING CURRENT BLOCK 

NOTE:- ALWAYS NEXT[i]= LAST[i]+ARR[LAST[i]] SINCE FORM LAST INDEX WE MAKE A JUMP TO REACH TO THE NEXT INDEX IN NEXT BLOCK...


ALL THESE 3 ARRAY CAN BE CALCULATED USING BACKWARD DP .......

for(int i=n-1;i>=0;i--) fix(i);




int fix(int i)
 {
//if ith index will directly go out of the block in next move  than  steps taken in the block=1,   //next=i+arr[i]  and last index  used in the same block will be i ..
    if((i+arr[i])>=n || (i+arr[i])/bs!=i/bs) 
         {
             nexxt[i]=i+arr[i];
cnt[i]=1;
last[i]=i;
}
// else if  remain i the same block , than count will be equal to count  of i+arr[i] , and also 
//  next   will be the next of i +arr[i] , ans last will be also same as last of i+arr[i] 
        else
{
cnt[i]=1+cnt[i+arr[i]];
nexxt[i]=nexxt[i+arr[i]];
 // cout<<" set last of "<<i<<" as "<<last[i+arr[i]]<<endl;
last[i]=last[i+arr[i]];
}
 }



now 
we have 2 types of  query ,
for type 1 query , we just need to count  the number for  jump , which can be easily calculate now 
start from the current node and add count[cur] for the current node( which will give answer for the no of moves taken inside the block ) ans than jump to the next block  ,, till no reach to  some index>=n
                            if(type)
       {
         int ans=0;
         int cur; 
         scanf("%d",&cur);
 cur--;
         int l=last[cur];
         while(cur<n)
                {
                   ans+=cnt[cur];//  add moves within same block 
                   l=last[cur];//  this node will be the last index used in current block 
                   cur=nexxt[cur]; //  go to next block 
}
printf("%d %d\n",(l+1),ans);
   }

for type 0 query , 

suppose we  update the value at index a , what are index affected due to that ,,
obviously some  indexs < a since these   are the index can go through  'a'

now according to  our method we have calculated next[i] , count[i] , and last[i] for each block 

so the answer of the  index which lies in some block < than the block of 'a'  can be affected but we need to update the next , count, and last of  index in the current block only , since  index in other block < than current block   can use the    values of of this block ..( if they reach in this block).

                           else// calling fix function for all index < a and in the  block of a 
   {
     int  a,b;
    scanf("%d %d",&a,&b);
      a--;
      arr[a]=b;
     int cur=a;
     while(cur>=0 && cur/bs==a/bs)
      {
       fix(cur);
       cur--;
  }
   }


===============================CODE=================================
#include<bits/stdc++.h>
using namespace std;
int arr[1000000];
int nexxt[1000000];
int cnt[1000000];
int last[1000000];
int bs=350;
 int n,q;
int fix(int i)
 {
    if((i+arr[i])>=n || (i+arr[i])/bs!=i/bs) 
    {
     nexxt[i]=i+arr[i];
cnt[i]=1;
last[i]=i;
}
else
{
cnt[i]=1+cnt[i+arr[i]];
nexxt[i]=nexxt[i+arr[i]];
 // cout<<" set last of "<<i<<" as "<<last[i+arr[i]]<<endl;
last[i]=last[i+arr[i]];
}
 }
int main()
 {
   
     cin>>n>>q;
     for(int i=0;i<n;i++)
       { 
        scanf("%d",&arr[i]);
 }
 
 for(int i=n-1;i>=0;i--)
  {
     fix(i);
  }
  
  for(int i=0;i<q;i++)
   {
     int type;
      scanf("%d",&type);
      if(type)
       {
         int ans=0;
         int cur; 
         scanf("%d",&cur);
 cur--;
         int l=last[cur];
         while(cur<n)
                {
                   ans+=cnt[cur];
                   l=last[cur];
                   cur=nexxt[cur]; 
}
printf("%d %d\n",(l+1),ans);
   }
   else
   {
     int  a,b;
    scanf("%d %d",&a,&b);
      a--;
      arr[a]=b;
     int cur=a;
     while(cur>=0 && cur/bs==a/bs)
      {
       fix(cur);
       cur--;
  }
   }
   }
 }

====================================OR===========================
Let's divide all row into blocks of length K=sqrt(N) of consecutive holes. If N is not a complete square, then we will take K=sqrt(N) rounded down. For each hole we will maintain not only it's power (let's call it power[i]), but also the number of the first hole which belongs to other block and which can be reached from the current one with sequence of jumps (let's call it next[i]). Also, for each hole we will maintain the number of jumps required to reach the hole next[i] from the current one (let's call it count[i]). We will consider that there is a fictious hole, which lies after the hole N and it belongs to it's own block.

To answer the query of the first type (when the ball is thrown) we will jump from the hole i to hole next[i] and so on, until we reach the fictious hole. Each time we will add count[i] to the answer. We will jump not more than N/K times.
To maintain the query of the seqond type (when the power of hole i is changed) we will change power[i], next[i] and count[i]. Then for each hole which belongs to the same block as i and has smaller number than i we will update next[i] and power[i] in decreasing order of number of the hole. We will perform not more than K updates.

The complexity is O(Nsqrt(N)).


Monday, 18 April 2016

****D. Babaei and Birthday Cake( maximum sum in increasing sub sequence )


D. Babaei and Birthday Cake


As you know, every birthday party has a cake! This time, Babaei is going to prepare the very special birthday party's cake.
Simple cake is a cylinder of some radius and height. The volume of the simple cake is equal to the volume of corresponding cylinder. Babaei has n simple cakes and he is going to make a special cake placing some cylinders on each other.
However, there are some additional culinary restrictions. The cakes are numbered in such a way that the cake number i can be placed only on the table or on some cake number j where j < i. Moreover, in order to impress friends Babaei will put the cake i on top of the cake j only if the volume of the cake i is strictly greater than the volume of the cake j.
Babaei wants to prepare a birthday cake that has a maximum possible total volume. Help him find this value.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of simple cakes Babaei has.
Each of the following n lines contains two integers ri and hi (1 ≤ ri, hi ≤ 10 000), giving the radius and height of the i-th cake.
Output
Print the maximum volume of the cake that Babaei can make. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.
Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .
Examples
input
2
100 30
40 10
output
942477.796077000
input
4
1 1
9 7
1 4
10 7
output
3983.539484752
Note
In first sample, the optimal way is to choose the cake number 1.
In second sample, the way to get the maximum volume is to use cakes with indices 12 and 4.

------------------------------------------------------editorial-----------------------------------------------------------------------------
this is a simple question we need to find maximum sum in an array and all included elements must be strictly increasing,
means we have to find maximum sum in increasing sub sequence ..
first come with a brute  dp approach ,  dp[i]=max(dp[i], dp[j]+val[i]) for all j<i and val[j]< val[i] ,
this can be easily computed in o(n^2) , but we have to it in the o(nlogn) complexity ,
for  that we have to use a segment  tree approach ,
sort all the values in  pair ((r*r*h) , index)  means minimum volume first ,  before  now start computing from the first, before computing ans for a volume r*r*h we need to  computed value of all volume < than its volume and is in the left of it , since we have sort according to the r*r*h than it is sure that  all volume < its volume computed , 
now we have to find best answer from all volumes < its volume and is in the right of it , this can be done using range max query easily, but main problem is that some of the vol < its vol can be in the right of this index also , how to not consider that , for that at the time of updating value of any vol update it at its original index not at the sorted index position , and also for query  find according to the original index not at the sorted index ,,, its confusing see the code for clarity ,,.. or read next editorial..
--------------------------------------------EDITORIAL-----------------------------------------------------------------------------
 First of all, we calculate the volume of each cake: vi = Ï€ × hi × ri2.
Now consider the sequence v1v2v3, ..., vn : The answer to the problem is the maximum sum of elements between all increasing sub-sequences of this sequence. How do we solve this? First to get rid of the decimals we can define a new sequence a1a2a3, ..., ansuch that 
We consider dpi as the maximum sum between all the sequences which end with ai and
dpi = 
The answer to the problem is: Ï€ × maxi = 1ndp[i]
Now how do we calculate  ? We use a max-segment tree which does these two operations: 1. Change the i't member to v2. Find the maximum value in the interval 1 to i.
Now we use this segment tree for the array dp and find the answer.
Consider that a1a2a3, ..., an is sorted. We define bi as the position of ai. Now to fill dpi we find the maximum in the interval [1, bi) in segment and we call it x and we set the bi th index of the segment as ai + x. The answer to the problem would the maximum in the segment in the interval [1,n]
Time complexity: O(nlgn)

-------------------------------------------------------code---------------------------------------------------
#include<bits/stdc++.h>
typedef long long int lli;
using namespace std;
lli dp[1000000];
#include<iostream>
using namespace std;
#define inf -9999999999999999
bool comp(pair<long long, int> a, pair<long long, int> b)
{
if (a.first != b.first)
return a.first < b.first;
return a.second>b.second;
}
lli  query(lli node,lli start,lli end,lli r1,lli r2)
 {  
 if(start>end || r1>end || r2<start) return 0;

   if(r1<=start && r2>=end)
    {
     return dp[node];
    }
    else
    {
     lli  q1=query(2*node,start,(start+end)/2,r1,r2);
    lli  q2=query(2*node+1,((start+end)/2)+1,end,r1,r2);
     return max(q1,q2);
    }
 }
void update(lli node ,lli start,lli end,lli r1,lli r2,lli val)
 {

  if(r1>end  || r2<start   || start>end) return  ;

  if(r1<=start && r2>=end)
   {
     dp[node]+=val;
      return  ;
   }
    update(2*node, start,(start+end)/2,r1,r2,val);
    update(2*node+1, ((start+end)/2)+1,end,r1,r2,val);
   dp[node]=max(dp[2*node],dp[2*node+1]);
 }
int  main()
 {
  lli n;
  scanf("%lld",&n);
  vector<pair<lli,lli> > v;
  for(lli i=0;i<n;i++)
   {
     lli h,r;
     scanf("%lld %lld",&r,&h);
     v.push_back({r*r*h,i});  
  }
  sort(v.begin(),v.end(),comp);
  lli ans=0;
  for(lli i=0;i<n;i++)
   {
     lli vol=v[i].first;
      lli index=v[i].second;
      
      lli maxi=query(1,0,n-1,0,index-1);
      // cout<<" maxi is "<<maxi<<endl;
      
      update(1,0,n-1,index,index,maxi+vol);
    }
    ans=query(1,0,n-1,0,n-1);
    
    
   double dd=3.1415926535897932384626433*(double)ans;
   printf("%.12lf",dd);
 }



-----------------------------------------ANOTHER SIMILAR PROB--------------------------------

Susobhan in BorrowLand 


All submissions for this problem are available.


Mr Susobhan lives in the city of Borrow-Land. He is looking to borrow as much money he can before he catches a flight to London. The city of Borrow-Land can be considered as an infinite grid. There are n lenders in the city located at a point (xi , yi ) who can lend at most Wi money. But Mr Susobhan borrows all the money the lender has.
No two lenders share the same location and no lender is present at point (0,0). Initially Mr Susobhan has no money and he starts at point (0, 0) in his expedition of borrowing money. Mr Susobhan is lazy and he can move only in two directions.
  • up from point (x,y) to (x,y+1)
  • right from point (x,y) to (x + 1, y)

Input

The first line of input contains an integer n denoting the number of lenders.
The next n lines contain three space separated numbers xiyi, and wi denoting the xth coordinate , yth coordinate and the money of the lender respectively.

Output

Print the maximum amount in a new line.

Constraints

  • 1 ≤ n ≤ 100000
  • 0 ≤ xi,yi ≤ 1000000000
  • 1 ≤ wi ≤ 1000000000


Example

Input:
3
1 2 20
2 6 10
1 8 5

Output:
30

---------------------------------------------------------CODE-----------------------------------------------------------------------------------------
  1. #include<bits/stdc++.h>
  2. typedef long long int lli;
  3. using namespace std;
  4. lli dp[1000000];
  5. #include<iostream>
  6. #define ff first
  7. #define ss second
  8. using namespace std;
  9. #define inf -9999999999999999
  10. #define mp make_pair
  11. #define pb push_back
  12.  
  13. lli query(lli node,lli start,lli end,lli r1,lli r2)
  14. {
  15. if(r1>r2)
  16. return 0;
  17. if(start>end || r1>end || r2<start) return 0;
  18.  
  19. if(r1<=start && r2>=end)
  20. {
  21. return dp[node];
  22. }
  23. else
  24. {
  25. lli q1=query(2*node,start,(start+end)/2,r1,r2);
  26. lli q2=query(2*node+1,((start+end)/2)+1,end,r1,r2);
  27. return max(q1,q2);
  28. }
  29. }
  30. void update(lli node ,lli start,lli end,lli r1,lli r2,lli val)
  31. {
  32. if(r1>end || r2<start || start>end) return ;
  33.  
  34. if(r1<=start && r2>=end)
  35. {
  36. dp[node]=val;
  37. return ;
  38. }
  39. update(2*node, start,(start+end)/2,r1,r2,val);
  40. update(2*node+1, ((start+end)/2)+1,end,r1,r2,val);
  41. dp[node]=max(dp[2*node],dp[2*node+1]);
  42. }
  43. int main()
  44. {
  45. lli n;
  46. scanf("%lld",&n);
  47. vector<pair<pair<lli,lli>,lli> > qq,vv;
  48. vector<pair<lli,lli> > v;
  49. vector<lli> comp;
  50. for(lli i=0;i<n;i++)
  51. {
  52. lli h,r,val;
  53. scanf("%lld %lld %lld",&r,&h,&val);
  54. qq.push_back(mp(mp(r,h),val));
  55. comp.pb(r);
  56. comp.pb(h);
  57. }
  58. sort(comp.begin(),comp.end());
  59. vector<lli>::iterator it;
  60. for(int i=0;i<n;i++)
  61. {
  62. int val1=qq[i].ff.ff;
  63. int val2=qq[i].ff.ss;
  64. it=lower_bound(comp.begin(),comp.end(),val1);
  65. int pos1=it-comp.begin();
  66. it=lower_bound(comp.begin(),comp.end(),val2);
  67. int pos2=it-comp.begin();
  68. vv.pb(mp(mp(pos1,pos2),qq[i].ss));
  69. }
  70. sort(vv.begin(),vv.end());
  71. // for(int i=0;i<n;i++)
  72. // {
  73. // cout<<vv[i].ff.ff<<" "<<vv[i].ff.ss<<" "<<vv[i].ss<<endl;
  74. //}
  75. for(int i=0;i<n;i++)
  76. {
  77. v.pb(mp(vv[i].ff.ss,vv[i].ss));
  78. }
  79. lli ans=0;
  80. for(lli i=0;i<n;i++)
  81. {
  82. lli vol=v[i].ss;
  83. lli index=v[i].ff;
  84. // cout<<" idx "<<index<<" "<<vol<<endl;
  85. lli maxi=query(1,0,2*n,0,index);
  86. // cout<<" maxi is "<<maxi<<endl;
  87. update(1,0,2*n,index,index,maxi+vol);
  88. }
  89. ans=query(1,0,2*n,0,2*n);
  90. cout<<ans<<endl;
  91. return 0;
  92. }