[atcoder 353] [題解】

fishcanfly發表於2024-05-12

C: Sigma Problem

  • 二分查詢
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        int n = rd.nextInt();
        long[] a = new long[n];
        for (int i = 0; i < n; i++) {
            a[i] = rd.nextInt();
        }
        Arrays.sort(a);
        long[] sum = new long[n];
        sum[0] = a[0];
        for (int i = 1; i < n; i++) {
            sum[i] = sum[i - 1] + a[i];
        }

        long ans = 0;
        for (int i = 1; i < n; i++) {
            // 第一個大於等於
            int insertPoint = lowerBound(a,0, i, 1000_000_00 - a[i]);

            // 1 , 1000_000_00 - 1
            // from 0 .. insertPoint -1 之間的數就可以直接算出來
            long before = 0;
            if (insertPoint > 0) {
                before += (sum[insertPoint - 1] + a[i] * insertPoint);
            }
            long after = 0;
            if (insertPoint < i) {
                after += (sum[i - 1] - (insertPoint == 0 ? 0 : sum[insertPoint - 1]) - (1000_000_00L - a[i]) * (i - insertPoint));
            }
            ans += (before + after);
        }
        System.out.println(ans);
    }

    /**
     * [from, to) 找到第一個>=target的數的index, 未找到是返回to
     *
     * @param a
     * @param from
     * @param to
     * @param target
     * @return
     */
    public static int lowerBound(long[] a, int from, int to, long target) {
        int low = from;
        int high = to;

        while(low < high) {
            int mid = (low + high) / 2;

            if ( a[mid] >= target) {
                high = mid;
            }
            else {
                low = mid + 1;
            }
        }
        return low;
    }

    static class rd {
        static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        static StringTokenizer tokenizer = new StringTokenizer("");

        // nextLine()讀取字串
        static String nextLine() throws IOException {
            return reader.readLine();
        }

        // next()讀取字串
        static String next() throws IOException {
            while (!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
            return tokenizer.nextToken();
        }

        // 讀取一個int型數值
        static int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        // 讀取一個double型數值
        static double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        // 讀取一個long型數值
        static long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        // 讀取一個BigInteger
        static BigInteger nextBigInteger() throws IOException {
            BigInteger d = new BigInteger(rd.nextLine());
            return d;
        }
    }
}

D Another Sigma Problem

  • 字首和
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        int n = rd.nextInt();
        int[] a = new int[n];
        long[] sum = new long[n];
        for (int i = 0; i < n; i++) {
            a[i] = rd.nextInt();
            if (i == 0) {
                sum[i] = a[0];
            } else {
                sum[i] = sum[i - 1] + a[i];
                sum[i] %= 998244353;
            }
        }
        //
        long ans = 0;
        for (int i = 1; i < n; i++) {
            ans += f(a, i, sum) % 998244353;
            ans %= 998244353;
        }
        System.out.println(ans);
    }

    public static long f(int[] a, int i, long[] sum) {
        long base = 1;
        long num = a[i];
        while (num != 0) {
            num = num / 10;
            base = base * 10 % 998244353;
            base %= 998244353;
        }
        return sum[i - 1] % 998244353 * base % 998244353  + (long)i % 998244353 * (long)a[i] % 998244353 ;
    }

}

class rd {
    static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer tokenizer = new StringTokenizer("");

    // nextLine()讀取字串
    static String nextLine() throws IOException {
        return reader.readLine();
    }

    // next()讀取字串
    static String next() throws IOException {
        while (!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
        return tokenizer.nextToken();
    }

    // 讀取一個int型數值
    static int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    // 讀取一個double型數值
    static double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }

    // 讀取一個long型數值
    static long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    // 讀取一個BigInteger
    static BigInteger nextBigInteger() throws IOException {
        BigInteger d = new BigInteger(rd.nextLine());
        return d;
    }
}

E - Yet Another Sigma Problem

  • trie樹

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int n;

    static class TrieNode {
        TrieNode[] children = new TrieNode[26];
        int cnt = 0;
        int depth = 0;
        char ch;

        public long getValue() {
            return (long)cnt * (cnt - 1) / 2;
        }

        public TrieNode(char ch) {
            this.ch = ch;
            for (int i = 0; i < 26; i++) {
                children[i] = null;
            }
            this.cnt = 0;
            this.depth = 0;
        }

        public TrieNode getChild(char ch) {
            return children[ch - 'a'];
        }

        public TrieNode(int parentDepth, char ch) {
            this.depth = parentDepth + 1;
            this.ch = ch;
            this.cnt = 1;
            for (int i = 0; i < 26; i++) {
                children[i] = null;
            }
        }

        public void addChild(TrieNode child) {
            this.children[child.ch - 'a'] = child;
        }
    }


    static TrieNode dummy = new TrieNode('a');

    public static void build(String str) {
        TrieNode curr = dummy;
        for (int i = 0; i < str.length(); i++) {
            int parentDepth = curr.depth;
            char ch1 = str.charAt(i);

            TrieNode child = curr.getChild(ch1);

            if (child != null) {
                child.cnt++;
            } else {
                child = new TrieNode(parentDepth, ch1);
                curr.addChild(child);
            }
            curr = child;
        }
    }

    public static long travel() {
        ArrayDeque<TrieNode> arrayDeque = new ArrayDeque<>();
        arrayDeque.add(dummy);

        long ans = 0;
        while (!arrayDeque.isEmpty()) {
            TrieNode node = arrayDeque.poll();
            long val1 = node.getValue();
            long val2 = 0;
            for (int i = 0; i < 26; i++) {
                if (node.children[i] != null) {
                    val2 += node.children[i].getValue();
                    arrayDeque.add(node.children[i]);
                }
            }
            ans += (val1 - val2) * node.depth;
        }
        return ans;
    }

    public static void main(String[] args) throws IOException {
        n = rd.nextInt();
        String[] str = rd.nextLine().split(" ");
        for (int i = 0; i < n; i++) {
            build(str[i]);
        }
        long ans = travel();
        System.out.println(ans);
    }

    static class rd {
        static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        static StringTokenizer tokenizer = new StringTokenizer("");

        // nextLine()讀取字串
        static String nextLine() throws IOException {
            return reader.readLine();
        }

        // next()讀取字串
        static String next() throws IOException {
            while (!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
            return tokenizer.nextToken();
        }

        // 讀取一個int型數值
        static int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        // 讀取一個double型數值
        static double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        // 讀取一個long型數值
        static long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        // 讀取一個BigInteger
        static BigInteger nextBigInteger() throws IOException {
            BigInteger d = new BigInteger(rd.nextLine());
            return d;
        }
    }
}

相關文章