bool QuadTree_S::Exists(const BitString &code, int x, int y) {
	DeltaCode delta;
	uint64_t cur = 0;
	long long nodes = delta.DecodeNextInt(code, &cur);
	long long size = code.get_length();
	long long nextIndx = 0;
	long long begRow = 0, begCol = 0, endRow = nodes, endCol = nodes;
	long long depth = 0,  nodesAtDepth = 1, nodesAtNextDepth = 0;
	for (long long i = 0; i < size;) {
		for(long long j = i; j < nodesAtDepth + i; j++) {	
			int curQuad = code.GetBit((j*2+cur)) << 1 | code.GetBit((j*2)+cur+1);
			if (j == nextIndx) {
				if (curQuad == 3) {
					double midRow = ((double)begRow + endRow)/2;
					double midCol = ((double)begCol + endCol)/2;
					if (x < midRow) { //We are in NE or NW
						if (y < midCol) { //We are in NW
							endRow = midRow;
							endCol = midCol;
							nextIndx = i + nodesAtDepth + nodesAtNextDepth;
						} else { //We are in NE
							endRow = midRow;
							begCol = midCol;
							nextIndx = i + nodesAtDepth + nodesAtNextDepth + 1;
						}
					} else if (y < midCol) { //We are in SW
						begRow = midRow;
						endCol = midCol;
						nextIndx = i + nodesAtDepth + nodesAtNextDepth + 2;
					} else { //We are in SE
						begRow = midRow;
						begCol = midCol;
						nextIndx = i + nodesAtDepth + nodesAtNextDepth + 3;
					}
					nodesAtNextDepth += 4;

					int nextQuad = code.GetBit((nextIndx*2)+cur) << 1 | code.GetBit((nextIndx*2)+cur+1);
					if (nextQuad == 1) return true;
					if (nextQuad == 0) return false;
					else if (nextQuad == 2)
						if (begCol-begRow + x == y) return false;
						else return true;
				} 
				else if (curQuad == 1) return true;
				else if (curQuad == 0) return false;
				else if (curQuad == 2) {
					if (begCol-begRow + x == y) return false;
					else return true;
				}
			} else if (curQuad == 3) {
				nodesAtNextDepth += 4;
			}
		}
		i += nodesAtDepth;
		nodesAtDepth = nodesAtNextDepth;
		nodesAtNextDepth = 0;
	}	
}
std::vector<int> QuadTree_H::GetNeighbors(const BitString &code, int x) {
	DeltaCode delta;
	uint64_t cur = 0;
	int nodes = delta.DecodeNextInt(code, &cur);
	long long size = code.get_length();
	long long freq[4] = {0, 3, 1, 2};
	cur += 8;
	std::vector<int> neighbors;
	QueueObj pos;
	std::queue<QueueObj> posQueue;
	posQueue.push(QueueObj(0, 0, nodes, 0, nodes));
	pos = posQueue.front();
	long long depth = 0,  nodesAtDepth = 1, nodesAtNextDepth = 0;
	for(int i = 0; !posQueue.empty();) {
		for(long long j = i; j < nodesAtDepth + i; j++) {	
			int curQuad = GetNextHuffQuad(code, freq, &cur);
			if (j == pos.nextPos) {
				posQueue.pop();
				if (curQuad == 3) {
					double midRow = ((double)pos.begRow + pos.endRow)/2;
					double midCol = ((double)pos.begCol + pos.endCol)/2;
					if (x < midRow) {
						posQueue.push(QueueObj(i + nodesAtDepth + nodesAtNextDepth, pos.begRow, midRow, pos.begCol, midCol));
						posQueue.push(QueueObj(i + nodesAtDepth + nodesAtNextDepth + 1, pos.begRow, midRow, midCol, pos.endCol));
					} else {
						posQueue.push(QueueObj(i + nodesAtDepth + nodesAtNextDepth + 2, midRow, pos.endRow, pos.begCol, midCol));
						posQueue.push(QueueObj(i + nodesAtDepth + nodesAtNextDepth + 3, midRow, pos.endRow, midCol, pos.endCol));
					}
					nodesAtNextDepth += 4;
				} 
				else if (curQuad == 1) {
					for (int n = pos.begCol; n < pos.endCol; ++n) {
						neighbors.push_back(n);
					}
				}
				else if (curQuad == 2) {
					for (int n = pos.begCol; n < pos.endCol; ++n) {
						if (pos.begCol - pos.begRow + x == n) continue;
						neighbors.push_back(n);
					}
				}
				if (posQueue.empty()) break;
				pos = posQueue.front();
			} else if (curQuad == 3){
				nodesAtNextDepth += 4;
			}
		}
		i += nodesAtDepth;
		nodesAtDepth = nodesAtNextDepth;
		nodesAtNextDepth = 0;
	}
	return neighbors;
}
void QuadTree_H::Compress(char * filename, const int &lineSkip, long long size, BitString * result) {
	std::vector<long long> quadStrings;
	std::ifstream fin(filename);
	std::string line;
	int x, y;
	for (int i = 0; i < lineSkip; ++i) std::getline(fin, line);
	while (std::getline(fin, line)) {
		std::stringstream ss(line);
		ss >> x >> y;		
		quadStrings.push_back(GetQuadString(size, x, y));
	}
	std::sort(quadStrings.begin(), quadStrings.end());
	long long currentString = GetQuadString(size, 0, 0);
	long long depth = LogFour(currentString);
	BitString * depthStrings = new BitString[depth];
	long long * depthSizes = new long long[depth];
	for (int i = 0; i < depth; ++i) depthSizes[i] = 0;
	long long freq[4] = {0, 0, 0, 0};
	long long dCommon, upQuad, upString, upCommon;
	dCommon = DeepestCommonQuad(depth, currentString, quadStrings[0]);
	upQuad = QuadAtDepth(quadStrings[0], depth - dCommon - 1);
	upString = StripNQuads(quadStrings[0], depth - dCommon - 1) - 1;
	upCommon = DeepestCommonQuad(depth, currentString, upString);
	if (currentString <= upString) {
		for (long long d = upCommon; d >= dCommon; --d) {
			long long curQuad = QuadAtDepth(currentString, depth - d - 1);
			long long upQuad = QuadAtDepth(upString, depth - d - 1);
			for (long long q = curQuad; q <= upQuad; ++q) {
				depthStrings[d].AppendBit(0);
				depthStrings[d].AppendBit(0);
				++depthSizes[d];
				++freq[0];
			}
			if (upQuad == 3) {
				for (long long y = d; y >= 1; --y) {
					if (!Compress(depthStrings, depthSizes, freq, y)) break;
				}
			}
		}
	}
	currentString = upString + 1;
	if (currentString < quadStrings[0]) {
		for (long long d = dCommon; d < depth; ++d) {
			long long curQuad = QuadAtDepth(currentString, depth - d - 1);
			long long edgeQuad = QuadAtDepth(quadStrings[0], depth - d - 1);
			for (long long q = curQuad; q < edgeQuad; ++q) {
				depthStrings[d].AppendBit(0);
				depthStrings[d].AppendBit(0);
				++depthSizes[d];
				++freq[0];
			}
			if (edgeQuad == 3) Compress(depthStrings, depthSizes, freq, d);
		}
		currentString = quadStrings[0];
	}
	depthStrings[depth-1].AppendBit(0);
	depthStrings[depth-1].AppendBit(1);
	++depthSizes[depth-1];
	++freq[1];
	for (long long d = depth - 1; d >= 1; --d) {
		if (!Compress(depthStrings, depthSizes, freq, d)) break;
	}
	for (int i = 1; i < quadStrings.size(); ++i) {
		dCommon = DeepestCommonQuad(depth, currentString, quadStrings[i]);
		upQuad = QuadAtDepth(quadStrings[i], depth - dCommon - 1);
		upString = StripNQuads(quadStrings[i], depth - dCommon - 1) - 1;
		upCommon = DeepestCommonQuad(depth, currentString, upString);
		if (currentString < upString) {
			for (long long d = depth - 1; d >= dCommon; --d) {
				long long curQuad = QuadAtDepth(currentString, depth - d - 1);
				long long upQuad = QuadAtDepth(upString, depth - d - 1);
				for (int q = curQuad; q < upQuad; ++q) {
					depthStrings[d].AppendBit(0);
					depthStrings[d].AppendBit(0);
					++depthSizes[d];
					++freq[0];
				}
				if (upQuad == 3 && upQuad != curQuad) {
					for (long long y = d; y >= 1; --y) {
						if (!Compress(depthStrings, depthSizes, freq, y)) break;
					}
				}
			}
		}
		currentString = upString + 1;
		if (currentString < quadStrings[i]) {
			for (long long d = dCommon; d < depth; ++d) {
				long long curQuad = QuadAtDepth(currentString, depth - d - 1);
				long long edgeQuad = QuadAtDepth(quadStrings[i], depth - d - 1);
				for (long long q = curQuad; q < edgeQuad; ++q) {
					depthStrings[d].AppendBit(0);
					depthStrings[d].AppendBit(0);
					++depthSizes[d];
					++freq[0];
				}
				if (edgeQuad == 3 && edgeQuad != curQuad) {
					for (long long y = d; y >= 1; --y) {
						if (!Compress(depthStrings, depthSizes, freq, y)) break;
					}
				}
			}
			currentString = quadStrings[i];
		}
		depthStrings[depth-1].AppendBit(0);
		depthStrings[depth-1].AppendBit(1);
		++depthSizes[depth-1];
		++freq[1];
		for (long long d = depth - 1; d >= 1; --d) {
			if (!Compress(depthStrings, depthSizes, freq, d)) break;
		}
	}
	currentString = quadStrings.back();
	long long endString = GetQuadString(size, size - 1, size - 1);
	dCommon = DeepestCommonQuad(depth, currentString, endString);
	if (currentString < endString) {
		for (long long d = depth - 1; d >= 0; --d) {
			long long curQuad = QuadAtDepth(currentString, depth - d - 1);
			long long upQuad = QuadAtDepth(endString, depth - d - 1);
			for (long long q = curQuad; q < upQuad; ++q) {
				depthStrings[d].AppendBit(0);
				depthStrings[d].AppendBit(0);
				++depthSizes[d];
				++freq[0];
			}
			if (upQuad == 3 && curQuad != upQuad) {
				for (long long y = d; y >= 1; --y) {
					if (!Compress(depthStrings, depthSizes, freq, y)) break;
				}
			}
		}
	}
	result->Init(0);
	DeltaCode delta;
	BitString tmp;
	delta.EncodeInt(size, &tmp);
	result->AppendBitString(tmp);
	++freq[3];
	BitString huff[4];
	GetHuffStrings(result, freq, huff);
	result->AppendBitString(huff[3]);
	for (int i = 0; i < depth; ++i) {
		BitString * ds = &depthStrings[i];
		for ( long long j = 0; j < ds->get_length(); j+=2) {
			int quad = ds->GetBit(j) << 1 | ds->GetBit(j+1);
			result->AppendBitString(huff[quad]);
		}
	}
	result->PrintRUSAGE();
}
bool QuadTree_DP::Exists(const BitString &code, int x, int y) {
	DeltaCode delta;
	uint64_t cur = 0;
	long long nodes = delta.DecodeNextInt(code, &cur);
	long long depth = delta.DecodeNextInt(code, &cur);
	std::vector<long long> depthSizes(depth+1);
	depthSizes[0] = 1;
	for (int i = 1; i <= depth; ++i) {
		depthSizes[i] = delta.DecodeNextInt(code, &cur);
	}
	long long offset = cur;
	std::vector<long long> depthIndices(depth+2);
	depthIndices[0] = 0;
	for (int i = 1; i < depth + 2; ++i) {
		depthIndices[i] = depthSizes[i-1] + depthIndices[i-1];
	}
	long long size = code.get_length();
	long long nextIndx = 0;
	long long begRow = 0, begCol = 0, endRow = nodes, endCol = nodes;
	long long curDepth = 0,  nodesAtDepth = 1, nodesAtNextDepth = 0;
	for (long long i = 0; i < depth; ++i) {
		for(long long j = depthIndices[i]; j < depthIndices[i+1]; ++j) {	
			int curQuad = code.GetBit(offset+(j*2)) << 1 | code.GetBit(offset+(j*2)+1);
			if (j == nextIndx) {
				if (curQuad == 3) {
					double midRow = ((double)begRow + endRow)/2;
					double midCol = ((double)begCol + endCol)/2;
					if (x < midRow) { //We are in NE or NW
						if (y < midCol) { //We are in NW
							endRow = midRow;
							endCol = midCol;
							nextIndx = depthIndices[i+1] + nodesAtNextDepth;
						} else { //We are in NE
							endRow = midRow;
							begCol = midCol;
							nextIndx = depthIndices[i+1] + nodesAtNextDepth + 1;
						}
					} else if (y < midCol) { //We are in SW
						begRow = midRow;
						endCol = midCol;
						nextIndx = depthIndices[i+1] + nodesAtNextDepth + 2;
					} else { //We are in SE
						begRow = midRow;
						begCol = midCol;
						nextIndx = depthIndices[i+1] + nodesAtNextDepth + 3;
					}
					nodesAtNextDepth += 4;

					int nextQuad = code.GetBit(offset+(nextIndx*2)) << 1 | code.GetBit(offset+(nextIndx*2)+1);
					if (nextQuad == 1) return true;
					if (nextQuad == 0) return false;
					else if (nextQuad == 2)
						if (begCol-begRow + x == y) return false;
						else return true;
				} 
				else if (curQuad == 1) return true;
				else if (curQuad == 0) return false;
				else if (curQuad == 2) {
					if (begCol-begRow + x == y) return false;
					else return true;
				}
				break;

			} else if (curQuad == 3) {
				nodesAtNextDepth += 4;
			}
		}
		nodesAtDepth = nodesAtNextDepth;
		nodesAtNextDepth = 0;
	}	
}