๐Ÿ“‚ ์•Œ๊ณ ๋ฆฌ์ฆ˜_๋ฌธ์ œํ’€์ด/BOJ_๋ฐฑ์ค€

[๋ฐฑ์ค€ BOJ / JAVA] ๋‘ ๋ฐฐ์—ด์˜ ํ•ฉ (2143๋ฒˆ)

Amenable 2023. 12. 29. 12:10

๐Ÿ“˜ 1. ๋ฌธ์ œ ์†Œ๊ฐœ

 

2143๋ฒˆ: ๋‘ ๋ฐฐ์—ด์˜ ํ•ฉ

์ฒซ์งธ ์ค„์— T(-1,000,000,000 ≤ T ≤ 1,000,000,000)๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ๋‹ค์Œ ์ค„์—๋Š” n(1 ≤ n ≤ 1,000)์ด ์ฃผ์–ด์ง€๊ณ , ๊ทธ ๋‹ค์Œ ์ค„์— n๊ฐœ์˜ ์ •์ˆ˜๋กœ A[1], …, A[n]์ด ์ฃผ์–ด์ง„๋‹ค. ๋‹ค์Œ ์ค„์—๋Š” m(1 ≤ m ≤ 1,000)์ด ์ฃผ์–ด์ง€๊ณ , ๊ทธ

www.acmicpc.net

  ํ•ด๋‹น ๋ฌธ์ œ๋Š” ์ด๋ถ„ ํƒ์ƒ‰๊ณผ ํˆฌ ํฌ์ธํ„ฐ๋กœ ํ’€ ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ“˜ 2. ์ด๋ถ„ ํƒ์ƒ‰์„ ์ด์šฉํ•œ ํ’€์ด

๐Ÿงต 1. ํ’€์ด

  ๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒ๊ฐํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ๋– ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

  • A์™€ B์˜ ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ์„ ๊ตฌํ•œ๋‹ค.
  • A์˜ ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ์„ ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ๋Œ๋ฉด์„œ, B์˜ ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ์—์„œ ์ด๋ถ„ ํƒ์ƒ‰์„ ์ด์šฉํ•˜์—ฌ T๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ์ฐพ๋Š”๋‹ค. (๋ฌผ๋ก  B์˜ ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ์„ ๊ธฐ์ค€์œผ๋กœ ๋ฐ˜๋ณต๋ฌธ์„ ๋Œ์•„๋„ ๋œ๋‹ค.)

  ํ•˜์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. ๋ฐฐ์—ด์— ์ค‘๋ณต๋˜๋Š” ๊ฐ’์ด ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์ˆœํžˆ ์ด๋ถ„ํƒ์ƒ‰์œผ๋กœ ๊ฐ’์ด ์žˆ๋Š”์ง€ ์—†๋Š”์ง€๋งŒ ์ฐพ์€ ๊ฒƒ์ด ์•„๋‹Œ ์กฐ๊ฑด์— ์ถฉ์กฑํ•˜๋Š” ๊ฐ’์ด ๋ช‡ ๊ฐœ๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ์ฐพ์•„์•ผ ํ•œ๋‹ค.

 

  ์ด๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด Lower Bound์™€ Upper Bound๋‹ค.

  • Lower Bound 
    ์ฐพ๊ณ ์ž ํ•˜๋Š” ๊ฐ’ ์ด์ƒ์ด ์ฒ˜์Œ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ์œ„์น˜
    ์ฆ‰, ์ฐพ๊ณ ์ž ํ•˜๋Š” ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ ๊ทธ ์ด์ƒ์˜ ๊ฐ’์ด ์ฒ˜์Œ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ์œ„์น˜๋ฅผ ์•Œ๋ ค์ค€๋‹ค.
  • Upper Bound 
    ์ฐพ๊ณ ์ž ํ•˜๋Š” ๊ฐ’๋ณด๋‹ค ํฐ ๊ฐ’์ด ์ฒ˜์Œ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ์œ„์น˜

Lower Bound์™€ Upper Bound๋ฅผ ์ด์šฉํ•˜์—ฌ ์กฐ๊ฑด์— ์ถฉ์กฑํ•˜๋Š” ๊ฐ’์˜ ๊ฐœ์ˆ˜๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿงต 2. ์ฝ”๋“œ

public class Main {

    static int T, N, M;
    static long ansCnt;
    static int[] numsA, numsB, sumA, sumB, partA, partB;
    static String[] ss;

    public static void main(String[] args) throws Exception {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        T = Integer.parseInt(in.readLine());
        N = Integer.parseInt(in.readLine());
        numsA = new int[N];
        sumA = new int[N + 1];


        ss = in.readLine().split(" ");

        for(int i = 0; i < N; i++) {
            numsA[i] = Integer.parseInt(ss[i]);
            // ๋ˆ„์ ํ•ฉ
            sumA[i + 1] = sumA[i] + numsA[i];
        }

        // ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ
        int temp = 0;
        partA = new int[((N + 1) * (N)) / 2];
        for(int cnt = 1; cnt <= N; cnt++) {
            for(int st = 0; st + cnt <= N; st++) {
                partA[temp++] = sumA[st + cnt] - sumA[st];
            }
        }

        M = Integer.parseInt(in.readLine());
        numsB = new int[M];
        sumB = new int[M + 1];

        ss = in.readLine().split(" ");

        for(int i = 0; i < M; i++) {
            numsB[i] = Integer.parseInt(ss[i]);
            // ๋ˆ„์ ํ•ฉ
            sumB[i + 1] = sumB[i] + numsB[i];
        }

        // ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ
        temp = 0;
        partB = new int[((M + 1) * (M)) / 2];
        for(int cnt = 1; cnt <= M; cnt++) {
            for(int st = 0; st + cnt <= M; st++) {
                partB[temp++] = sumB[st + cnt] - sumB[st];
            }
        }

        Arrays.sort(partA);
        Arrays.sort(partB);

        // 1. ์ด๋ถ„ ํƒ์ƒ‰์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
        for(int i = 0; i < partA.length; i++) {
            int aValue = partA[i];
            int bValue = T - aValue;

            // bValue์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ•˜๊ธฐ
            int bValueCnt = upperBound(partB, bValue) - lowerBound(partB, bValue);

            ansCnt += bValueCnt;
        }

        System.out.println(ansCnt);
    }

    private static int lowerBound(int[] arr, int key) {
        int l = 0;
        int r = arr.length;

        while(l < r) {
            int mid = (l + r) / 2;
            if(arr[mid] < key)
                l = mid + 1;
            else
                r = mid;
        }

        return r;
    }

    private static int upperBound(int[] arr, int key) {
        int l = 0;
        int r = arr.length;

        while(l < r) {
            int mid = (l + r) / 2;
            if(arr[mid] <= key)
                l = mid + 1;
            else
                r = mid;
        }

        return r;
    }
}

 

๐Ÿ“˜ 3. ํˆฌ ํฌ์ธํ„ฐ๋ฅผ ์ด์šฉํ•œ ํ’€์ด

๐Ÿงต 1. ํ’€์ด

  ๊ฒฐ๊ตญ A์˜ ๋ถ€ ๋ฐฐ์—ด์˜ ๊ฐ’๊ณผ B์˜ ๋ถ€ ๋ฐฐ์—ด์˜ ๊ฐ’์„ ๋”ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ํˆฌ ํฌ์ธํ„ฐ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ถ€ ๋ฐฐ์—ด์„ ์ •๋ ฌํ•œ ํ›„, A๋Š” ์ œ์ผ ์™ผ์ชฝ์—์„œ ์‹œ์ž‘ํ•˜๊ณ  B๋Š” ์ œ์ผ ์˜ค๋ฅธ์ชฝ์—์„œ ์‹œ์ž‘ํ•˜๋ฉด ๋œ๋‹ค. (๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.)

  ๊ทธ๋ฆฌ๊ณ  ๊ฐ ํฌ์ธํ„ฐ์˜ ํ•ฉ์ด T๋ณด๋‹ค ์ž‘์€ ๊ฒฝ์šฐ A๋ฅผ ์˜ค๋ฅธ์ชฝ์œผ๋กœ, T๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ B๋ฅผ ์™ผ์ชฝ์œผ๋กœ ์ด๋™ํ•˜๋ฉด ๋œ๋‹ค. ํ•ฉ์ด T์ธ ๊ฒฝ์šฐ์—๋Š” ๋‹จ์ˆœํžˆ ์นด์šดํŠธ๋ฅผ +1๋งŒ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ์ค‘๋ณต๋œ ๊ฐ’์ด ๋ช‡ ๊ฐœ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์—ฌ ๊ทธ์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์„ cnt์— ๋”ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

 

๐Ÿงต 2. ์ฝ”๋“œ

public class Main {

    static int T, N, M;
    static long ansCnt;
    static int[] numsA, numsB, sumA, sumB, partA, partB;
    static String[] ss;

    public static void main(String[] args) throws Exception {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

        T = Integer.parseInt(in.readLine());
        N = Integer.parseInt(in.readLine());
        numsA = new int[N];
        sumA = new int[N + 1];


        ss = in.readLine().split(" ");

        for(int i = 0; i < N; i++) {
            numsA[i] = Integer.parseInt(ss[i]);
            // ๋ˆ„์ ํ•ฉ
            sumA[i + 1] = sumA[i] + numsA[i];
        }

        // ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ
        int temp = 0;
        partA = new int[((N + 1) * (N)) / 2];
        for(int cnt = 1; cnt <= N; cnt++) {
            for(int st = 0; st + cnt <= N; st++) {
                partA[temp++] = sumA[st + cnt] - sumA[st];
            }
        }

        M = Integer.parseInt(in.readLine());
        numsB = new int[M];
        sumB = new int[M + 1];

        ss = in.readLine().split(" ");

        for(int i = 0; i < M; i++) {
            numsB[i] = Integer.parseInt(ss[i]);
            // ๋ˆ„์ ํ•ฉ
            sumB[i + 1] = sumB[i] + numsB[i];
        }

        // ๋ถ€ ๋ฐฐ์—ด์˜ ํ•ฉ
        temp = 0;
        partB = new int[((M + 1) * (M)) / 2];
        for(int cnt = 1; cnt <= M; cnt++) {
            for(int st = 0; st + cnt <= M; st++) {
                partB[temp++] = sumB[st + cnt] - sumB[st];
            }
        }

        Arrays.sort(partA);
        Arrays.sort(partB);

        // 2. ํˆฌ ํฌ์ธํ„ฐ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
        int aLeft = 0;
        int bRight = partB.length - 1;
        while(aLeft < partA.length && 0 <= bRight) {
            int aValue = partA[aLeft];
            int bValue = partB[bRight];

            if(aValue + bValue == T) {
                // ์ค‘๋ณต๋œ ๊ฐ’๋“ค์„ ์นด์šดํŠธ
                long aCnt = 0L;
                long bCnt = 0L;
                while(aLeft < partA.length && aValue == partA[aLeft]) {
                    aLeft++;
                    aCnt++;
                }
                while(0 <= bRight && bValue == partB[bRight]) {
                    bRight--;
                    bCnt++;
                }

                ansCnt += aCnt * bCnt;
            }
            else if(aValue + bValue < T) {
                aLeft++;
            }
            else {
                bRight--;
            }
        }

        System.out.println(ansCnt);
    }
}