public void fill(long from, long to) {
		if (from > to)
			throw new IndexOutOfBoundsException("from: " + from + " > to: " + to);
		if (from == to) {
			add(from);
			return;
		}

		final long firstBlockIndex = (from / SUBSET_SIZE) * SUBSET_SIZE;
		final long lastBlockIndex = (to / SUBSET_SIZE) * SUBSET_SIZE;
		if (firstBlockIndex == lastBlockIndex) {
			// Case 1: One block
			if (firstBlockIndex == 0L) {
				firstIndices.fill((int) from, (int) to);
			} else {
				IntSet s = otherIndices.get(firstBlockIndex);
				if (s == null)
					otherIndices.put(firstBlockIndex, s = firstIndices.empty());
				s.fill((int) (from - firstBlockIndex), (int) (to - firstBlockIndex));
			}
		} else {
			// Case 2: Multiple blocks
			// Handle first block
			if (firstBlockIndex == 0L) {
				firstIndices.fill((int) from, SUBSET_SIZE - 1);
			} else {
				IntSet s = otherIndices.get(firstBlockIndex);
				if (s == null)
					otherIndices.put(firstBlockIndex, s = firstIndices.empty());
				s.fill((int) (from - firstBlockIndex), SUBSET_SIZE - 1);
			}

			// Handle intermediate words, if any
			for (long i = firstBlockIndex + SUBSET_SIZE; i < lastBlockIndex; i += SUBSET_SIZE) {
				IntSet s = firstIndices.empty();
				s.fill(0, SUBSET_SIZE - 1);
				otherIndices.put(i, s);
			}

			// Handle last word
			IntSet s = otherIndices.get(lastBlockIndex);
			if (s == null)
				otherIndices.put(lastBlockIndex, s = firstIndices.empty());
			s.fill(0, (int) (to - lastBlockIndex));
		}
	}