提出 #70627631


ソースコード 拡げる

import java.io.*;
import java.util.*;

class Main {

    static class BIT {
        private final int size;
        private final long[] tree;

        public BIT(int size) {
            this.size = size;
            this.tree = new long[size + 1];
        }

        // Updates the value at index i by delta. (1-based index)
        public void update(int i, long delta) {
            for (; i <= size; i += i & -i) {
                tree[i] += delta;
            }
        }

        // Returns the cumulative sum from 1 to i. (1-based index)
        public long query(int i) {
            long sum = 0;
            for (; i > 0; i -= i & -i) {
                sum += tree[i];
            }
            return sum;
        }

        // Returns the sum from L to R inclusive.
        public long queryRange(int L, int R) {
            if (L > R) return 0;
            return query(R) - query(L - 1);
        }
    }

    static class Event {
        int pa;   // The coordinate to sweep over (P_a or P_a - A)
        int pb;   // The other coordinate (P_b or P_b - B + 1)
        int type; // 0 for point addition, 1 for query
        int id;   // Original index k for points or r for queries

        public Event(int pa, int pb, int type, int id) {
            this.pa = pa;
            this.pb = pb;
            this.type = type;
            this.id = id;
        }
    }

    public static void main(String[] args) throws IOException {
        FastScanner fs = new FastScanner();

        int N = fs.nextInt();
        int A = fs.nextInt();
        int B = fs.nextInt();
        String S = fs.next();

        int[] Pa = new int[N + 1]; // Prefix count of 'a's (0-indexed P[0]=0, P[N]=total)
        int[] Pb = new int[N + 1]; // Prefix count of 'b's

        for (int i = 0; i < N; i++) {
            Pa[i + 1] = Pa[i] + (S.charAt(i) == 'a' ? 1 : 0);
            Pb[i + 1] = Pb[i] + (S.charAt(i) == 'b' ? 1 : 0);
        }

        List<Event> events = new ArrayList<>();
        // Add point events (k = l-1, from 0 to N-1)
        // We only care about points up to k=r-1, so k goes from 0 to N-1
        for (int k = 0; k < N; k++) {
            events.add(new Event(Pa[k], Pb[k], 0, k));
        }

        // Add query events (r from 1 to N)
        // Query: P_a[k] <= P_a[r] - A  (pa_max)
        //        P_b[k] >= P_b[r] - B + 1 (pb_min)
        for (int r = 1; r <= N; r++) {
            int pa_max = Pa[r] - A;
            int pb_min = Pb[r] - B + 1;
            
            // We only need to consider points where P_a[k] <= pa_max
            // We sweep on P_a, so pa_max is the coordinate.
            // P_b values are 0-indexed, so we can use them directly in BIT if we 1-index it.
            events.add(new Event(pa_max, pb_min, 1, r));
        }

        // Sort events: Primary key P_a (ascending), Secondary key type (0 before 1), Tertiary key P_b (ascending)
        events.sort((e1, e2) -> {
            if (e1.pa != e2.pa) return Integer.compare(e1.pa, e2.pa);
            if (e1.type != e2.type) return Integer.compare(e1.type, e2.type); // Process add points before queries
            return Integer.compare(e1.pb, e2.pb);
        });

        // The maximum value for P_b is N. BIT size N+1 (0 to N).
        // We use 1-based indexing for BIT, so the indices will be [1, N+1] for values [0, N].
        BIT bit = new BIT(N + 1);
        long totalPairs = 0;

        for (Event event : events) {
            if (event.type == 0) { // Add point (P_a[k], P_b[k])
                // P_b values are 0-indexed, so add 1 for BIT index
                bit.update(event.pb + 1, 1);
            } else { // Query for (P_a[r]-A, P_b[r]-B+1)
                // We are looking for P_b[k] >= P_b[r] - B + 1 (event.pb)
                // The minimum P_b value for the range is event.pb.
                
                // BIT stores count for P_b values: P_b[k] >= event.pb
                // Max P_b is N (index N+1 in BIT). Min P_b in range is event.pb (index event.pb + 1 in BIT).
                int pb_min_bit_index = event.pb + 1;
                
                // Clamp pb_min_bit_index to 1 (min P_b value is 0)
                pb_min_bit_index = Math.max(1, pb_min_bit_index);
                
                // Clamp pb_min_bit_index to N+1 (max P_b value is N)
                pb_min_bit_index = Math.min(N + 1, pb_min_bit_index);
                
                // Count = total - count(P_b[k] < event.pb)
                // P_b[k] < event.pb means P_b[k] <= event.pb - 1
                // BIT index for P_b[k] <= event.pb - 1 is (event.pb - 1) + 1 = event.pb
                int pb_max_negation_bit_index = event.pb; 
                
                // Clamp pb_max_negation_bit_index to N+1
                pb_max_negation_bit_index = Math.min(N + 1, pb_max_negation_bit_index);

                // Total count of points added so far
                long totalPoints = bit.query(N + 1); 
                // Count of points with P_b[k] <= event.pb - 1
                long negationCount = bit.query(pb_max_negation_bit_index); 
                
                long count = totalPoints - negationCount;
                totalPairs += count;
            }
        }

        System.out.println(totalPairs);
    }

    static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

提出情報

提出日時
問題 C - Truck Driver
ユーザ addy
言語 Java24 (OpenJDK 24.0.2)
得点 300
コード長 6452 Byte
結果 AC
実行時間 277 ms
メモリ 85364 KiB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 300 / 300
結果
AC × 2
AC × 25
セット名 テストケース
Sample sample_01.txt, sample_02.txt
All hand.txt, random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt, random_18.txt, random_19.txt, random_20.txt, random_21.txt, random_22.txt, sample_01.txt, sample_02.txt
ケース名 結果 実行時間 メモリ
hand.txt AC 50 ms 38416 KiB
random_01.txt AC 236 ms 85032 KiB
random_02.txt AC 238 ms 84928 KiB
random_03.txt AC 236 ms 85208 KiB
random_04.txt AC 241 ms 84964 KiB
random_05.txt AC 239 ms 84948 KiB
random_06.txt AC 238 ms 84968 KiB
random_07.txt AC 227 ms 84760 KiB
random_08.txt AC 232 ms 84812 KiB
random_09.txt AC 235 ms 85188 KiB
random_10.txt AC 237 ms 85036 KiB
random_11.txt AC 234 ms 85000 KiB
random_12.txt AC 230 ms 84872 KiB
random_13.txt AC 231 ms 85060 KiB
random_14.txt AC 233 ms 84988 KiB
random_15.txt AC 230 ms 84996 KiB
random_16.txt AC 237 ms 85000 KiB
random_17.txt AC 277 ms 85164 KiB
random_18.txt AC 257 ms 85176 KiB
random_19.txt AC 230 ms 85260 KiB
random_20.txt AC 214 ms 85364 KiB
random_21.txt AC 237 ms 85152 KiB
random_22.txt AC 223 ms 84960 KiB
sample_01.txt AC 51 ms 38328 KiB
sample_02.txt AC 50 ms 38564 KiB