diff --git a/algo/local_improving.cpp b/algo/local_improving.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..06484a7caf31a5d514136f893ce96dc92f7cf768
--- /dev/null
+++ b/algo/local_improving.cpp
@@ -0,0 +1,64 @@
+#include "../pipe.h"
+#include <functional>
+#include <cassert>
+
+// ****** ARGS ********
+// <int>    max number of changes
+
+using std::pair;
+
+const int VERSION = 2;
+const bool ALLOW_INPUT_MISTAKES = 0;
+const bool ALLOW_MISTAKES = 0;
+
+vector<bool> solve(int n, vector<int> input, vector<bool> out,
+		int argc, char const* const* argv)
+{
+	assert(argc==1);
+	int max_changes = atoi(argv[0]);
+	assert(max_changes > 0);
+
+	vector<int> other = lib::gen_arr_other_car_of_type(n, input);
+
+	std::function<bool (int, int , int)> f = [&](int changes, int score_diff, int begin_index)
+	{
+		for(int i=begin_index; i<2*n;i++) if(i < other[i])
+		{
+			out[i] = !out[i];
+			out[other[i]] = !out[other[i]];
+
+			int new_score_diff = score_diff;
+			if(i) new_score_diff += out[i]==out[i-1] ? -1 : 1;
+			if(i+1 != other[i])
+			{
+				new_score_diff += out[i]==out[i+1] ? -1 : 1;
+				new_score_diff += out[other[i]]==out[other[i]-1] ? -1 : 1;
+			}
+			if(other[i]!=2*n-1) new_score_diff += out[other[i]]==out[other[i]+1] ? -1 : 1;
+
+			if(new_score_diff < 0)
+			{
+				fprintf(stderr, "%d %d %d\n", changes, i, new_score_diff);
+				return true;
+			}
+
+
+			if(changes+1 < max_changes)
+				if(f(changes+1, new_score_diff, i+1))
+					return true;
+
+			out[i] = !out[i];
+			out[other[i]] = !out[other[i]];
+		}
+		return false;
+	};
+
+	while (f(0, 0, 0))
+	{
+
+		fo(i, 2*n) fprintf(stderr, "%c", out[i]?'1':'0');
+		fprintf(stderr, "\n", n);
+	}
+
+	return out;
+}
diff --git a/algo/rg.cpp b/algo/rg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81b769d4c394700e7267229ad5aa60b4ed3ceabf
--- /dev/null
+++ b/algo/rg.cpp
@@ -0,0 +1,42 @@
+#include "../main.h"
+
+const int VERSION = 1;
+const bool ALLOW_MISTAKES = 0;
+
+vector<bool> solve(int n, vector<int> input,
+		int argc, char const* const* argv)
+{
+	if(n == 0) return vector<bool>();
+	vector<int> other = lib::gen_arr_other_car_of_type(n, input);
+	vector<bool> out(2*n);
+
+	vector<int> r_input(2*n-2);
+	for(int i=1;i<2*n;i++) if(i != other[0])
+		r_input[i - 1 - (i>other[0])] = input[i] - (input[i] > input[0]);
+
+	auto r_out = solve(n-1, r_input, argc, argv);
+
+	for(int i=1;i<2*n;i++) if(i != other[0])
+		out[i] = r_out[i - 1 - (i>other[0])];
+
+	if(other[0] == 2*n-1)
+	{
+		out[0] = 1;
+		out[other[0]] = 0;
+	}
+	else if(other[0] == 1)
+	{
+		out[0] = !out[2];
+		out[1] = out[2];
+	}
+	else
+	{
+		if(out[other[0]-1] == out[1] && out[other[0]+1] == out[1])
+			out[0] = !out[1];
+		else
+			out[0] = out[1];
+		out[other[0]] = !out[0];
+	}
+
+	return out;
+}
diff --git a/algo/rsg.cpp b/algo/rsg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..47895a2fba073a73fbabaaa3c11f87882074509f
--- /dev/null
+++ b/algo/rsg.cpp
@@ -0,0 +1,96 @@
+#include "../main.h"
+
+const int VERSION = 1;
+const bool ALLOW_MISTAKES = 0;
+
+
+vector<int> solve_star(int n, vector<int> input)
+{
+	if(n == 0) return vector<int>();
+	vector<int> other = lib::gen_arr_other_car_of_type(n, input);
+	vector<int> out(2*n); // 0: * -1, 1: colors
+
+	vector<int> r_input(2*n-2);
+	for(int i=1;i<2*n;i++) if(i != other[0])
+		r_input[i - 1 - (i>other[0])] = input[i] - (input[i] > input[0]);
+
+	auto r_out = solve_star(n-1, r_input);
+
+	for(int i=1;i<2*n;i++) if(i != other[0])
+		out[i] = r_out[i - 1 - (i>other[0])];
+
+	if(other[0] == 2*n-1) // B
+	{
+		out[0] = 1;
+		out[other[0]] = -1;
+	}
+	else if(other[0] == 1) // A
+	{
+		out[0] = -out[2];
+		out[1] = out[2];
+	}
+	else if(out[other[0]-1] == out[other[0]+1] && out[other[0]-1]) // C
+	{
+		out[0] = -out[other[0]-1];
+		out[other[0]] = out[other[0]-1];
+	}
+	else if(out[other[0]+1] && out[other[0]-1]) // D
+	{
+		out[0] = out[1];
+		out[other[0]] = -out[1];
+	}
+	else if(out[1] == -out[other[0]-1] || out[1] == -out[other[0]+1]) // E
+	{
+		out[0] = out[1];
+		out[other[0]] = -out[1];
+	}
+	else // F
+	{
+		out[0] = out[1];
+		out[other[0]] = -out[1];
+		if(!out[other[0]-1])
+		{
+			out[other[0]-1] = -out[1];
+			out[other[other[0]-1]] = out[1];
+		}
+		else
+		{
+			out[other[0]+1] = -out[1];
+			out[other[other[0]+1]] = out[1];
+		}
+	}
+
+	if(other[1] != 2 && other[1] != 2*n-1 
+			&& out[1-1] && out[1+1]
+			&& out[other[1]-1] && out[other[1]+1]) // G
+	{
+		int diffs = 0;
+		diffs += out[1] != out[1-1];
+		diffs += out[1] != out[1+1];
+		diffs += out[other[1]] != out[other[1]-1];
+		diffs += out[other[1]] != out[other[1]+1];
+		if(diffs == 2)
+		{
+			out[1] = out[other[1]] = 0;
+		}
+	}
+	//fo(i, 2*n) fprintf(stderr, "%c", out[i]?out[i]==1?'1':'0':'*');
+	//fprintf(stderr, "\n", n);
+	return out;
+}
+
+vector<bool> solve(int n, vector<int> input,
+		int argc, char const* const* argv)
+{
+	vector<int> other = lib::gen_arr_other_car_of_type(n, input);
+	auto out_star = solve_star(n, input);
+	vector<bool> out(2*n);
+	fo(i, 2*n)
+	{
+		if(out_star[i])
+			out[i] = out_star[i] > 0;
+		else
+			out[i] = i > other[i];
+	}
+	return out;
+}
diff --git a/build.mk b/build.mk
index 9c8685ab1aed390a5c8e3a3d5332d15d84d8cc0b..1eb333fcceb69a6ec6dbb74139ab9c947ce14f18 100644
--- a/build.mk
+++ b/build.mk
@@ -58,7 +58,10 @@ endef
 $(eval $(call standard_algo,greedy))
 $(eval $(call standard_algo,maxcut))
 $(eval $(call standard_algo,semidef_prog))
+$(eval $(call standard_algo,rg))
+$(eval $(call standard_algo,rsg))
 
 $(eval $(call standard_pipe,fix_naive))
 $(eval $(call standard_pipe,fix_better))
+$(eval $(call standard_pipe,local_improving))
 
diff --git a/config.mk b/config.mk
index 0a26bc792f1e659c08f071f96645a2d0ba3760a2..732f4d3c2590167c25f3cb5d5035a55b0aff9bea 100644
--- a/config.mk
+++ b/config.mk
@@ -1 +1 @@
-algorithms=greedy maxcut fix_naive fix_better semidef_prog
+algorithms=greedy maxcut fix_naive fix_better semidef_prog local_improving rg rsg