- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 106 lines of Java from the credited upstream file 3017.java.
- The implementation visibly relies on sequence storage.
- 6 loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 3 public long[] countOfPairs(int n, int x, int y) {4 if (x > y) {5 final int temp = x;6 x = y;7 y = temp;8 }9 10 final int ringLen = y - x + 1;11 final int leftLineLen = x - 1;12 final int rightLineLen = n - y;13 14 long[] ans = new long[n];15 ans = addVectors(ans, bothInRing(n, ringLen));16 ans = addVectors(ans, bothInTheSameLine(n, leftLineLen));17 ans = addVectors(ans, bothInTheSameLine(n, rightLineLen));18 ans = addVectors(ans, lineToRing(n, leftLineLen, ringLen));19 ans = addVectors(ans, lineToRing(n, rightLineLen, ringLen));20 ans = addVectors(ans, lineToLine(n, x, y, leftLineLen, rightLineLen));21 for (int i = 0; i < ans.length; ++i)22 ans[i] *= 2;23 return ans;24 }25 26 27 28 private long[] bothInRing(int n, int ringLen) {29 long[] res = new long[n];30 for (int k = 1; k <= (ringLen - 1) / 2; ++k)31 res[k - 1] += ringLen;32 if (ringLen % 2 == 0)33 res[ringLen / 2 - 1] += ringLen / 2;34 return res;35 }36 37 38 39 private long[] bothInTheSameLine(int n, int lineLen) {40 long[] res = new long[n];41 for (int k = 1; k <= lineLen; ++k)42 res[k - 1] += lineLen - k;43 return res;44 }45 46 47 48 49 private long[] lineToRing(int n, int lineLen, int ringLen) {50 long[] res = new long[n];51 for (int k = 1; k <= lineLen + ringLen; ++k) {52 53 54 55 56 57 final int maxInRingLen = Math.min(k - 1, ringLen / 2);58 59 final int minInRingLen = Math.max(0, k - lineLen);60 if (minInRingLen <= maxInRingLen) {61 62 63 64 65 66 67 res[k - 1] += (maxInRingLen - minInRingLen + 1) * 2;68 if (minInRingLen == 0)69 70 res[k - 1] -= 1;71 if (maxInRingLen * 2 == ringLen)72 73 74 75 res[k - 1] -= 1;76 }77 }78 return res;79 }80 81 82 83 private long[] lineToLine(int n, int x, int y, int leftLineLen, int rightLineLen) {84 long[] res = new long[n];85 for (int k = 1; k <= leftLineLen + rightLineLen + 2; ++k) {86 87 88 89 90 91 final int maxInLeft = Math.min(leftLineLen, k - 1 - (x < y ? 1 : 0));92 93 final int minInLeft = Math.max(1, k - rightLineLen - (x < y ? 1 : 0));94 if (minInLeft <= maxInLeft)95 res[k - 1] += maxInLeft - minInLeft + 1;96 }97 return res;98 }99 100 private long[] addVectors(long[] a, long[] b) {101 for (int i = 0; i < a.length; ++i)102 a[i] += b[i];103 return a;104 }105}106