Better algorithm than O(nlogn)(or better implementation)

I have been trying to solve this SPOJ problem R2D2.

I have been using segment tree.But I am getting TLE.Time limit is 7s. Constraints on input is following:

T <= 10

n <= 10^6

This is my code:(Constant factor is also significant)

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

long int a[2000000],arr[2000000],seg[10000000][2];
char temp[20];
//Constructing segment tree.Storing array value in first column of seg[][] and array index in second column
long int ctrct(long int sb,long int se,long int si)
{
 if(sb == se)
 {
  seg[si][0] =  sb;
  seg[si][1] =  arr[sb];
 }
 else
 {
  long int mid = sb+(se-sb)/2;
  long int l = ctrct(sb,mid,2*si+1);
  long int r = ctrct(mid+1,se,2*si+2);
  if(arr[l] >= arr[r])
  {
   seg[si][0] = l;
   seg[si][1] = arr[l];
  }
  else
  {
   seg[si][0] = r;
   seg[si][1] = arr[r];
  }
 }
 return seg[si][0];
}
//getting maximum value in given range
long int getmax(long int ss,long int se,long int x,long int y,long int i)
{
 if(ss >= x && se <= y)
 {
  return seg[i][0];
 }
 else if(ss > y || se <x)
    return -1;
 else
 {
  long int mid = (ss+se)/2;
  long int l = getmax(ss,mid,x,y,2*i+1);
  long int r = getmax(mid+1,se,x,y,2*i+2);
  if(l == -1)
  {
   return r;
  }
  if(r == -1)
  {
   return l;
  }
  if(arr[l] >= arr[r])
    return l;
  else
    return r;
 }
}

void update(long int ss,long int se,long int x,long int val,long int i)
{
 if(ss > x || se < x)
    return;
 if(ss != se)
 {
  long int mid = (ss+se)/2;
  update(ss,mid,x,val,2*i+1);
  update(mid+1,se,x,val,2*i+2);
  if(seg[2*i+1][1] >= seg[2*i+2][1])
  {
   seg[i][1] = seg[2*i+1][1];
   seg[i][0] = seg[2*i+1][0];
  }
  else
  {
   seg[i][1] = seg[2*i+2][1];
   seg[i][0] = seg[2*i+2][0];
  }
 }
 else
 {
  if(ss == x)
  {
   seg[i][1] = val;
   seg[i][0] = x;
  }
 }
}

int main()
{
   long int n,i,j,k,r,v,T,ans,l,segsize,pos,ctr;
   scanf("%ld",&T);
   while(T > 0)
   {
    fflush(stdin);
    scanf("%ld",&k);
    scanf("%ld",&n);
    segsize = 2*(pow(2,ceil(log2(n))));
    for(i=0;i<10000000;i++)
    {
     seg[i][0] = -1;
     seg[i][1] = 0;
    }
    for(i=0;i<1000001;i++)
    {
     arr[i] = a[i] = 0;
    }
    std::cin.ignore(1);
    for(i=0;i<n;i++)
    {
     gets(temp);
     //Getting the input as per requirements
     if(strlen(temp) > 3 && temp[1] == ' ' && (temp[2] >= 48 && temp[2] <= '57'))
     {
      l = 2;
      r = 0;
      v = 0;
      while(temp[l] !=  ' ')
      {
       r = r*10 + (long int)(temp[l] - 48);
       l++;
      }
      l++;
      while(l < strlen(temp))
      {
       v = v*10 + (long int)(temp[l] - 48);
       l++;
      }
      for(j=0;j<r;j++,i++)
      {
        a[i] = v;
        arr[i] = k;
      }
      i--;
     }
     else
     {
      v = 0;
      l = 0;
      while(l < strlen(temp))
      {
       v = v*10 + (long int)(temp[l] - 48);
       l++;
      }
      a[i] = v;
      arr[i] = k;
     }
    }
    ctrct(0,n-1,0);
    ctr = 0;
    for(i=0;i<n;i++)
    {
     pos = getmax(0,n-1,0,ctr,0);
     //if for any index pos earlier than current max can fit the a[i] value than consider that position.Since always the first index of block is returned.
     if(pos > 0 && arr[pos-1] >= a[i])
     {
      while(arr[pos-1] >= a[i])
      {
       pos = getmax(0,n-1,0,pos-1,0);
      }  
     }
     if(arr[pos] < a[i])
     {
        ctr++;
        pos = getmax(0,n-1,0,ctr,0);
     }
     arr[pos] -= a[i];
     update(0,n-1,pos,arr[pos],0);
    }
    ans = 0;
    for(i = 0;i<=ctr;i++)
        ans += arr[i];
    printf("%ld %ld\n",(ctr+1),ans);
    T--;
   }
    return 0;
}

Please suggest some better algorithm or some optimization.

**EDIT:**In the question we need to select the ship:(1)that can hold container(2)that has minimum index.
So I am using segment tree to get the maximum capacity left in the range 0 to no. of ship being used(range possibly consist of 0s and left over space).Since maximum possible may have index greater than “sufficient” capacity available, I am recursively checking from previous ranges leading to a constant factor(assuming (1)most containers are in block(2)tried without checking for previous ranges,did’nt get WA but TLE).
Since we need to update the ship capacity and get the ship index I am using a structure to store both the index and value of ship. So I am getting the required index and updating it.I tried it on extreme limits:
T = 10
n = 10^6
I got 16.263s on codeblocks.

Do you mind describing your algorithm in a concise manner? Reading the code is a tedious task.

3 Likes