femboy's blog

By femboy, 16 months ago, In English

CSES time limits are actually so cancerous for java. I had to literally binary search for a viable max nodes for my Concert Tickets solution to work. However, in the end, my radix trie did indeed work! With 0.99 s on test case 5, I barely scrape by with another ac on these absolutely cancerous time constraints. If this didn't work, I was going to grab the FastIO from kattis and see if the few ms from that would save me. If that failed, then reading System.in.read(byte[]) would have to be my life.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class ticketmeisterofconcert {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);
        Tokenizer tr = new Tokenizer(in.readLine());
        IntegerMultiSetTree imst = new IntegerMultiSetTree();
        int n = tr.intToken();
        int m = tr.intToken();
        int[] c = new int[m];
        tr = new Tokenizer(in.readLine());
        for (int i = 0; i < n; ++i) imst.add(tr.intToken());
        tr = new Tokenizer(in.readLine());
        for (int i = 0; i < m; ++i) c[i] = tr.intToken();
        int[] pay = new int[m];
        for (int i = 0; i < m; ++i) {
            Integer q = imst.floor(c[i]);
            pay[i] = q;
            if (q != -1)imst.remove(q);
        }
        for (int uwu : pay) out.println(uwu);
        out.flush();
    }
    static class Tokenizer extends StringTokenizer {
        public Tokenizer(String in) { super(in); }
        public int intToken() { return Integer.parseInt(this.nextToken()); }
        public long longToken() { return Long.parseLong(this.nextToken()); }
        public double doubleToken() { return Double.parseDouble(this.nextToken()); }
    }
    static class IntegerMultiSetTree {
        static final int MAX_BITS = 30;
        static final int MAX_NODES = 5_360_000;

        int[] tree = new int[MAX_NODES*2];
        int[] count = new int[MAX_NODES];
        int ptr = 0;

        public void add(int a) {
            int t = 0;
            for (int i = 0; i < MAX_BITS; ++i) {
                int q = (a >>> MAX_BITS-1-i) & 1;
                if (tree[t+q] == 0) {
                    tree[t+q] = 2 * ++ptr;
                }
                ++count[t];
                t = tree[t+q];
            }
            ++count[t];
        }

        public void remove(int a) {
            int t = 0;
            --count[t];
            for (int i = 0; i < MAX_BITS; ++i) {
                int q = (a >>> MAX_BITS-1-i) & 1;
                int n = tree[t+q];
                if (--count[n] == 0) tree[t+q] = 0;
                if (tree[t+q] == 0) {
                    return;
                }
                t = tree[t+q];
            }
        }

        public int floor(int a) {
            int[] t = new int[MAX_BITS+1];
            return dfs(t, a, 0, 0);
        }
        private int dfs(int[] t, int a, int q, int uwu) {
            if (q == MAX_BITS) return uwu;
            for (int i = 1; i >= 0; --i) {
                if (uwu + (i << MAX_BITS-1-q) <= a) {
                    if (tree[t[q]+i] == 0) continue;
                    t[q+1] = tree[t[q]+i];
                    int b;
                    if ((b = dfs(t, a, q+1, uwu + (i << MAX_BITS-1-q))) != -1) return b;
                }
            }
            return -1;
        }
    }
}
  • Vote: I like it
  • +25
  • Vote: I do not like it

| Write comment?
»
16 months ago, hide # |
 
Vote: I like it +25 Vote: I do not like it

I'd very honestly recommend using c++ for cp instead of java, using c++ is not that hard for cp, if you already know java. Boxing also impacts performance a lot, also the fact that it's a JIT'd language, but the JIT does not really have time to kick in the time limits given in CP, so you are working with sub-par code generated.

Main drawbacks of cp like UB and dangling pointers are not that difficult manage in context of cp (actual software is another case)

The views api of c++20 makes it much more tolerable to use too