SRM410 div1 medium

#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
#include <climits>

using namespace std;
typedef long long LL;

int n;
LL k;
int range[55][55][2][2];
LL cache[55][55][2];

class ContiguousCache 
{
	public:

		LL intersect(int a1,int a2,int b1,int b2)
		{
			if(a1<=b1 && b1<=a2 && a2<=b2)
				return a2-b1+1;
			else if(a1<=b1 && b2<=a2)
				return b2-b1+1;
			else if(b1<=a1 && a2<=b2)
				return a2-a1+1;
			else if(b1<=a1 && a1<=b2 && b2<=a2)
				return b2-a1+1;
			else
				return 0;
		}

		LL rec(int a1,int a2,int slide)
		{
			int b1=a2+1,b2,nextSlide;
			LL &r=cache[a1][a2][slide];

			if(r!=-1)
				;
			else if(b1==n)
				r=0;
			else	
			{
				r=LLONG_MAX;
				for(b2=b1;b2<n && range[b1][b2][0][0]!=-1;b2++)
					for(nextSlide=0;nextSlide<2;nextSlide++)
						r=min(r,k-intersect(range[a1][a2][slide][0],range[a1][a2][slide][1],range[b1][b2][nextSlide][0],range[b1][b2][nextSlide][1])+rec(b1,b2,nextSlide));
			}

			return r;
		}

		LL minimumReads(int _n,int _k,vector<int> addresses) 
		{
			reverse(addresses.begin(),addresses.end());
			addresses.push_back(INT_MIN/2);
			reverse(addresses.begin(),addresses.end());

			n=addresses.size(),k=_k;
			for(int i=0;i<n;i++)
				for(int j=0;j<n;j++)
				{
					LL mi=INT_MAX/2,ma=INT_MIN/2;
					for(int l=min(i,j);l<=max(i,j);l++)
					{
						mi=min(mi,(LL)addresses[l]);
						ma=max(ma,(LL)addresses[l]);
					}
					range[i][j][0][0]=-1,range[i][j][0][1]=-1;
					range[i][j][1][0]=-1,range[i][j][1][1]=-1;
					if(ma-mi<k)
					{
						range[i][j][0][0]=mi,range[i][j][0][1]=mi+k-1;
						range[i][j][1][0]=ma-k+1,range[i][j][1][1]=ma;
					}
				}

			memset(cache,-1,sizeof(cache));
			return rec(0,0,0);
		}
};