public @NotNull SearchArea union(@NotNull SearchArea area) {
      int[] mergedStartOffsets = ArrayUtil.mergeArrays(startOffsets, area.startOffsets);
      int[] mergedEndOffsets = ArrayUtil.mergeArrays(endOffsets, area.endOffsets);
      Arrays.sort(mergedStartOffsets);
      Arrays.sort(mergedEndOffsets);

      final IntList resultStartOffsets = new IntArrayList(mergedStartOffsets.length);
      final IntList resultEndOffsets = new IntArrayList(mergedStartOffsets.length);

      new Object() {
        int counter = 0;
        int startsIndex = 0;
        int endsIndex = 0;

        void run() {
          while (startsIndex < mergedStartOffsets.length ||
                 endsIndex < mergedEndOffsets.length) {
            if (endsIndex == mergedEndOffsets.length) {
              Logger.getInstance(SearchArea.class).error(String.format("Merging invalid SearchArea: %s - %s", this, area));
              nextStart();
            }
            else if (startsIndex == mergedStartOffsets.length) {
              nextEnd();
            }
            else {
              int start = mergedStartOffsets[startsIndex];
              int end = mergedEndOffsets[endsIndex];
              if (start <= end) {
                nextStart();
              }
              else {
                nextEnd();
              }
            }
          }
        }

        void nextStart() {
          if (counter == 0) {
            int startOffset = mergedStartOffsets[startsIndex];
            resultStartOffsets.add(startOffset);
          }
          counter++;
          startsIndex++;
        }

        void nextEnd() {
          counter--;
          if (counter == 0) {
            int endOffset = mergedEndOffsets[endsIndex];
            resultEndOffsets.add(endOffset);
          }
          if (counter < 0) {
            Logger.getInstance(SearchArea.class).error(String.format("Merging invalid SearchArea: %s - %s", this, area));
          }
          endsIndex++;
        }
      }.run();

      return create(resultStartOffsets.toIntArray(), resultEndOffsets.toIntArray());
    }
public @NotNull SearchArea union(@NotNull SearchArea area)