#include "bits/stdc++.h"
#include <cmath>
using namespace std;

#define f first
#define s second

#define pb push_back
#define pp pop_back
#define mp make_pair

#define sz(x) (int)x.size()
#define sqr(x) ((x) * 1ll * (x))
#define all(x) x.begin(), x.end()
#define clr(a,v) memset(a, v, sizeof(a))

#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, l, r) for (int i = (l); i >= (r); i--)
#define reflex ios_base::sync_with_stdio(false)

#define nl '\n'
#define ioi exit(0);

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int N= (int)2e5 + 7;
const int inf = (int)1e9 + 7;
const int mod = (int)1e9 + 7;
//const int mod = 1000000007;
const ll linf = (ll)1e18 + 7;

const int dx[] = {-1, 0, 1, 0, 1, -1, -1, 1};
const int dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
const int kx[] = {-1,1,2,2,1,-1,-2,-2};
const int ky[] = {2,2,1,-1,-2,-2,-1,1};

string conv(int a){stringstream ss;ss << a;string str = ss.str();return str;}
string conv(char a){stringstream ss;ss << a;string str = ss.str();return str;}
int conv(string a){stringstream geek(a); int x = 0; geek >> x;   return x;}

struct node 
{ 
   int minimum; 
   int maximum; 
}; 
  

int getMid(int s, int e) {  return s + (e -s)/2;  } 
  
struct node MaxMinUntill(struct node *st, int ss, int se, int qs, 
                         int qe, int index) 
{ 
    
    struct node tmp,left,right; 
    if (qs <= ss && qe >= se) 
        return st[index]; 
  
    
    if (se < qs || ss > qe) 
    { 
       tmp.minimum = INT_MAX; 
       tmp.maximum = INT_MIN; 
       return tmp; 
     } 
  
    int mid = getMid(ss, se); 
    left = MaxMinUntill(st, ss, mid, qs, qe, 2*index+1); 
    right = MaxMinUntill(st, mid+1, se, qs, qe, 2*index+2); 
    tmp.minimum = min(left.minimum, right.minimum); 
    tmp.maximum = max(left.maximum, right.maximum); 
    return tmp; 
} 
  
 
struct node MaxMin(struct node *st, int n, int qs, int qe) 
{ 
    struct node tmp; 
  
    if (qs < 0 || qe > n-1 || qs > qe) 
    { 
        printf("Invalid Input"); 
        tmp.minimum = INT_MIN; 
        tmp.minimum = INT_MAX; 
        return tmp; 
    } 
  
    return MaxMinUntill(st, 0, n-1, qs, qe, 0); 
} 
  
void constructSTUtil(int arr[], int ss, int se, struct node *st, int si) 
{ 
    if (ss == se) 
    { 
        st[si].minimum = arr[ss]; 
        st[si].maximum = arr[ss]; 
        return ; 
    } 
  
    int mid = getMid(ss, se); 
    constructSTUtil(arr, ss, mid, st, si*2+1); 
    constructSTUtil(arr, mid+1, se, st, si*2+2); 
  
    st[si].minimum = min(st[si*2+1].minimum, st[si*2+2].minimum); 
    st[si].maximum = max(st[si*2+1].maximum, st[si*2+2].maximum); 
} 
  
struct node *constructST(int arr[], int n) 
{ 
    int x = (int)(ceil(log2(n))); 
  
    int max_size = 2*(int)pow(2, x) - 1; 
  
    struct node *st = new struct node[max_size]; 
  
    constructSTUtil(arr, 0, n-1, st, 0); 
  
    return st; 
} 


class UnionFind {                                              // OOP style
private:
	vector<int> p, rank, setSize;
	// p = path toward the root of disjoint set; p[i] = i means it is root
	// rank = upper bound of the actual height of the tree; not reliable as accurate measure
	// setSize = size of each disjoint set

	int numSets;
public:
	UnionFind(int N) {
		setSize.assign(N, 1);
		numSets = N;
		rank.assign(N, 0);
		p.assign(N, 0);
		for (int i = 0; i < N; i++) p[i] = i;	// each belongs to its own set
	}

	int findSet(int i) {
		return (p[i] == i) ? i : (p[i] = findSet(p[i]));		// path compression: cut short of the path if possible
	}

	bool isSameSet(int i, int j) {
		return findSet(i) == findSet(j);
	}

	void unionSet(int i, int j) {
		if (!isSameSet(i, j)) {
			numSets--;
			int x = findSet(i), y = findSet(j);
			// rank is used to keep the tree short
			if (rank[x] > rank[y]) { p[y] = x; setSize[x] += setSize[y]; }
			else {
				p[x] = y; setSize[y] += setSize[x];
				if (rank[x] == rank[y]) rank[y]++;
			}
		}
	}

	int numDisjointSets() {		// # of disjoint sets
		return numSets;
	}

	int sizeOfSet(int i) {		// size of set
		return setSize[findSet(i)];
	}
};


//~ // Prints shortest paths from src to all other vertices 
//~ void Graph::primMST() 
//~ { 
	//~ // Create a priority queue to store vertices that 
	//~ // are being preinMST. This is weird syntax in C++. 
	//~ // Refer below link for details of this syntax 
	//~ // http://geeksquiz.com/implement-min-heap-using-stl/ 
	//~ priority_queue< iPair, vector <iPair> , greater<iPair> > pq; 

	//~ int src = 0; // Taking vertex 0 as source 

	//~ // Create a vector for keys and initialize all 
	//~ // keys as infinite (INF) 
	//~ vector<int> key(V, INF); 

	//~ // To store parent array which in turn store MST 
	//~ vector<int> parent(V, -1); 

	//~ // To keep track of vertices included in MST 
	//~ vector<bool> inMST(V, false); 

	//~ // Insert source itself in priority queue and initialize 
	//~ // its key as 0. 
	//~ pq.push(make_pair(0, src)); 
	//~ key[src] = 0; 

	//~ /* Looping till priority queue becomes empty */
	//~ while (!pq.empty()) 
	//~ { 
		//~ // The first vertex in pair is the minimum key 
		//~ // vertex, extract it from priority queue. 
		//~ // vertex label is stored in second of pair (it 
		//~ // has to be done this way to keep the vertices 
		//~ // sorted key (key must be first item 
		//~ // in pair) 
		//~ int u = pq.top().second; 
		//~ pq.pop(); 

		//~ inMST[u] = true; // Include vertex in MST 

		//~ // 'i' is used to get all adjacent vertices of a vertex 
		//~ list< pair<int, int> >::iterator i; 
		//~ for (i = adj[u].begin(); i != adj[u].end(); ++i) 
		//~ { 
			//~ // Get vertex label and weight of current adjacent 
			//~ // of u. 
			//~ int v = (*i).first; 
			//~ int weight = (*i).second; 

			//~ // If v is not in MST and weight of (u,v) is smaller 
			//~ // than current key of v 
			//~ if (inMST[v] == false && key[v] > weight) 
			//~ { 
				//~ // Updating key of v 
				//~ key[v] = weight; 
				//~ pq.push(make_pair(key[v], v)); 
				//~ parent[v] = u; 
			//~ } 
		//~ } 
	//~ } 

	//~ // Print edges of MST using parent array 
	//~ for (int i = 1; i < V; ++i) 
		//~ printf("%d - %d\n", parent[i], i); 
//~ } 



int main() 
{ 
	int n, d; cin>> n >> d;
	int k = 0, r = 1 + 2*d, l;
	while(r < n){
		k++;
		l = r;
		r +=1 + 2*d; 
	}
	if(l < n)
		k++;
	cout<<k;
	return 0; 
} 



Measured memory_bytes: 256