import java.io.*; import java.util.*; public class...
Created on: August 10, 2025
Answered using GPT-5 Thinking by Chat01
Created on: August 10, 2025
Answered using GPT-5 Thinking by Chat01
import java.io.;
import java.util.;
public class Main {
static class FastScanner {
private final InputStream in = System.in;
private final byte[] buffer = new byte[1 << 16];
private int ptr = 0, len = 0;
private int read() throws IOException {
if (ptr >= len) {
len = in.read(buffer);
ptr = 0;
if (len <= 0) return -1;
}
return buffer[ptr++];
}
int nextInt() throws IOException {
int c;
while ((c = read()) <= 32) if (c == -1) return -1;
int sign = 1;
if (c == '-') { sign = -1; c = read(); }
int val = 0;
while (c > 32) {
val = val * 10 + c - '0';
c = read();
}
return val * sign;
}
String next() throws IOException {
int c;
while ((c = read()) <= 32) if (c == -1) return null;
StringBuilder sb = new StringBuilder();
while (c > 32) {
sb.append((char) c);
c = read();
}
return sb.toString();
}
}
public static void main(String[] args) throws Exception {
FastScanner fs = new FastScanner();
int t = fs.nextInt();
StringBuilder out = new StringBuilder();
while (t-- > 0) {
int n = fs.nextInt();
String a = fs.next();
String b = fs.next();
int[] prefA = new int[n+1];
int[] prefB = new int[n+1];
for (int i = 1; i <= n; i++) prefA[i] = prefA[i-1] + (a.charAt(i-1) == '1' ? 1 : 0);
for (int i = 1; i <= n; i++) prefB[i] = prefB[i-1] + (b.charAt(i-1) == '1' ? 1 : 0);
int[] delta = new int[n];
int[] B0 = new int[n];
int[] B1 = new int[n];
for (int y = 1; y <= n; y++) {
B0[y-1] = prefB[y];
B1[y-1] = y - prefB[y];
delta[y-1] = 2 * prefB[y] - y;
}
Integer[] idx = new Integer[n];
for (int i = 0; i < n; i++) idx[i] = i;
Arrays.sort(idx, (i,j) -> Integer.compare(delta[i], delta[j]));
long[] prefB0 = new long[n+1];
long[] prefB1 = new long[n+1];
int[] sortedDelta = new int[n];
for (int i = 1; i <= n; i++) {
int id = idx[i-1];
sortedDelta[i-1] = delta[id];
prefB0[i] = prefB0[i-1] + B0[id];
prefB1[i] = prefB1[i-1] + B1[id];
}
long totalB1 = prefB1[n];
long ans = 0;
for (int x = 1; x <= n; x++) {
int A0 = prefA[x];
int A1 = x - A0;
int Dx = 2 * A0 - x;
int T = -Dx;
int lo = 0, hi = n - 1, pos = -1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
if (sortedDelta[mid] <= T) {
pos = mid;
lo = mid + 1;
} else hi = mid - 1;
}
int k = pos + 1;
long sum1 = (long)k * A0 + prefB0[k];
long sum2 = (long)(n - k) * A1 + (totalB1 - prefB1[k]);
ans += sum1 + sum2;
}
out.append(ans).append('\n');
}
System.out.print(out.toString());
}
}
simplify the code
Here’s a cleaner, shorter version with clearer names, one binary-search helper, and fewer temporary arrays—same logic and complexity (O(n log n)):
javaimport java.io.*; import java.util.*; public class Main { static class FastScanner { private final InputStream in = System.in; private final byte[] buf = new byte[1 << 16]; private int ptr = 0, len = 0; private int read() throws IOException { if (ptr >= len) { len = in.read(buf); ptr = 0; if (len <= 0) return -1; } return buf[ptr++]; } int nextInt() throws IOException { int c; while ((c = read()) <= 32) if (c == -1) return -1; int sign = 1; if (c == '-') { sign = -1; c = read(); } int v = 0; while (c > 32) { v = v * 10 + (c - '0'); c = read(); } return v * sign; } String next() throws IOException { int c; while ((c = read()) <= 32) if (c == -1) return null; StringBuilder sb = new StringBuilder(); while (c > 32) { sb.append((char) c); c = read(); } return sb.toString(); } } static class Node { int delta; // ones - zeros in B prefix int bOnes; // ones in B prefix int bZeros; // zeros in B prefix Node(int delta, int bOnes, int bZeros) { this.delta = delta; this.bOnes = bOnes; this.bZeros = bZeros; } } // returns last index with a[i] <= target (upper bound - 1), or -1 if none static int upperBound(int[] a, int target) { int lo = 0, hi = a.length - 1, ans = -1; while (lo <= hi) { int mid = (lo + hi) >>> 1; if (a[mid] <= target) { ans = mid; lo = mid + 1; } else hi = mid - 1; } return ans; } public static void main(String[] args) throws Exception { FastScanner fs = new FastScanner(); int t = fs.nextInt(); StringBuilder out = new StringBuilder(); while (t-- > 0) { int n = fs.nextInt(); String a = fs.next(); String b = fs.next(); // prefix ones counts for A and B int[] pa = new int[n + 1], pb = new int[n + 1]; for (int i = 1; i <= n; i++) { pa[i] = pa[i - 1] + (a.charAt(i - 1) - '0'); pb[i] = pb[i - 1] + (b.charAt(i - 1) - '0'); } // Build nodes for each B prefix, then sort by delta Node[] nodes = new Node[n]; for (int y = 1; y <= n; y++) { int ones = pb[y]; int zeros = y - ones; nodes[y - 1] = new Node(ones - zeros, ones, zeros); // delta = 2*ones - y } Arrays.sort(nodes, Comparator.comparingInt(nd -> nd.delta)); // Prepare arrays for binary search and prefix sums over sorted B prefixes int[] deltas = new int[n]; long[] prefOnesB = new long[n + 1]; long[] prefZerosB = new long[n + 1]; for (int i = 1; i <= n; i++) { Node nd = nodes[i - 1]; deltas[i - 1] = nd.delta; prefOnesB[i] = prefOnesB[i - 1] + nd.bOnes; prefZerosB[i] = prefZerosB[i - 1] + nd.bZeros; } long totalZerosB = prefZerosB[n]; long ans = 0; for (int x = 1; x <= n; x++) { int onesA = pa[x]; int zerosA = x - onesA; int deltaA = onesA - zerosA; // 2*onesA - x int threshold = -deltaA; int k = upperBound(deltas, threshold) + 1; // # of B prefixes with delta <= threshold long sum1 = (long) k * onesA + prefOnesB[k]; long sum2 = (long) (n - k) * zerosA + (totalZerosB - prefZerosB[k]); ans += sum1 + sum2; } out.append(ans).append('\n'); } System.out.print(out.toString()); } }
Key changes: clearer names, a small Node
to avoid parallel arrays + index indirection, a reusable upperBound
, and comments so the flow is easy to follow.