제출 #254799

#제출 시각아이디문제언어결과실행 시간메모리
254799model_codeViruses (BOI20_viruses)Java
100 / 100
641 ms41508 KiB
import java.io.*;
import java.util.*;

public class Viruses {

    private static class Val implements Comparable<Val> {

        private final long value;
        private final int i;
        private final int st;
        private final int en;

        public Val(long value, int i, int st, int en) {
            this.value = value;
            this.i = i;
            this.st = st;
            this.en = en;
        }

        @Override
        public int compareTo(Val o) {
            if (this.value < o.value) {
                return -1;
            } else if (this.value > o.value) {
                return 1;
            } else {
                if (this.i < o.i) {
                    return -1;
                } else if (this.i > o.i) {
                    return 1;
                } else {
                    if (this.st < o.st) {
                        return -1;
                    } else if (this.st > o.st) {
                        return 1;
                    } else {
                        if (this.en < o.en) {
                            return -1;
                        } else if (this.en > o.en) {
                            return 1;
                        } else {
                            return 0;
                        }
                    }
                }
            }
        }
    }

    private static class Mutation {

        private final int st;
        private final int en1;
        private final Integer en2;

        public Mutation(int st, int en1) {
            this.st = st;
            this.en1 = en1;
            this.en2 = null;
        }

        public Mutation(int st, int en1, int en2) {
            this.st = st;
            this.en1 = en1;
            this.en2 = en2;
        }
    }

    private static final int MAXG = 305;
    private static final int MAXL = 55;
    private static final long MYINFLL = 1000000000000000000L;

    private static long[] a = new long[MAXG * MAXL * MAXL + 1];

    private static void set(int i, int st, int en, long val) {
        a[MAXL * MAXL * i + MAXL * st + en] = val;
    }

    private static long get(int i, int st, int en) {
        return a[MAXL * MAXL * i + MAXL * st + en];
    }

    private static TreeSet<Val> q = new TreeSet<>();

    private static void update(int i, int st, int en, long val) {
        long cur = get(i, st, en);
        if (val < cur) {
            q.remove(new Val(cur, i, st, en));
            set(i, st, en, val);
            q.add(new Val(val, i, st, en));
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        String str;
        String[] params;

        str = br.readLine();
        params = str.split(" ");
        int G = Integer.parseInt(params[0]);
        int N = Integer.parseInt(params[1]);
        int M = Integer.parseInt(params[2]);
        int origG = G;

        ArrayList<Mutation> mutations = new ArrayList<>();

        for (int i = 0; i < N; i++) {
            str = br.readLine();
            params = str.split(" ");
            int startGene = Integer.parseInt(params[0]);
            int len = Integer.parseInt(params[1]);

            if (len == 1) {
                int endGene = Integer.parseInt(params[2]);
                mutations.add(new Mutation(startGene, endGene));
            } else {
                int cur = startGene;
                int pos = 2;
                while (true) {
                    int nextGene = Integer.parseInt(params[pos]);
                    pos++;
                    len--;
                    if (len == 1) {
                        int finalGene = Integer.parseInt(params[pos]);
                        mutations.add(new Mutation(cur, nextGene, finalGene));
                        break;
                    }
                    mutations.add(new Mutation(cur, nextGene, G));
                    cur = G;
                    G++;
                }
            }
        }

        int[] mutationsByRhsSt = new int[G + 1];
        for (int i = 0; i <= G; i++) {
            mutationsByRhsSt[i] = 0;
        }
        for (int ind = 0; ind < mutations.size(); ind++) {
            Mutation rhs = mutations.get(ind);
            if ((rhs.en2 == null) || (rhs.en2.equals(rhs.en1))) {
                mutationsByRhsSt[rhs.en1]++;
            } else {
                mutationsByRhsSt[rhs.en1]++;
                mutationsByRhsSt[rhs.en2]++;
            }
        }
        for (int i = 1; i <= G; i++) {
            mutationsByRhsSt[i] += mutationsByRhsSt[i - 1];
        }
        int[] mutationsByRhs = new int[mutationsByRhsSt[G] + 1];
        for (int ind = 0; ind < mutations.size(); ind++) {
            Mutation rhs = mutations.get(ind);
            if ((rhs.en2 == null) || (rhs.en2.equals(rhs.en1))) {
                mutationsByRhsSt[rhs.en1]--;
                mutationsByRhs[mutationsByRhsSt[rhs.en1]] = ind;
            } else {
                mutationsByRhsSt[rhs.en1]--;
                mutationsByRhs[mutationsByRhsSt[rhs.en1]] = ind;
                mutationsByRhsSt[rhs.en2]--;
                mutationsByRhs[mutationsByRhsSt[rhs.en2]] = ind;
            }
        }

        Set<String> keywords = new HashSet<>();
        Set<String> prefixesSet = new HashSet<>();
        prefixesSet.add("");

        for (int i = 0; i < M; i++) {
            str = br.readLine();
            params = str.split(" ");
            int len = Integer.parseInt(params[0]);

            String s = "";
            for (int j = 0; j < len; j++) {
                int elem = Integer.parseInt(params[j + 1]);
                s += elem == 1 ? "1" : "0";
            }
            keywords.add(s);
            for (int j = 1; j <= len; j++) {
                prefixesSet.add(s.substring(0, j));
            }
        }

        ArrayList<String> prefixes = new ArrayList<>(prefixesSet.size());
        ArrayList<Boolean> prefixesIsTerminal = new ArrayList<>(prefixesSet.size());
        Map<String, Integer> indexes = new HashMap<>();
        for (String prefix : prefixesSet) {
            indexes.put(prefix, prefixes.size());
            prefixes.add(prefix);

            boolean isTerminal = false;
            for (int i = 0; i < prefix.length(); i++) {
                if (keywords.contains(prefix.substring(i))) {
                    isTerminal = true;
                }
            }

            prefixesIsTerminal.add(isTerminal);
        }

        int S = prefixes.size();

        for (int i = 0; i < G; i++) {
            for (int st = 0; st < S; st++) {
                for (int en = 0; en < S; en++) {
                    set(i, st, en, MYINFLL);
                }
            }
        }

        for (int st = 0; st < S; st++) {
            if (!prefixesIsTerminal.get(st)) {
                for (int i = 0; i < 2; i++) {
                    String s = prefixes.get(st) + (i == 0 ? "0" : "1");
                    while (!prefixesSet.contains(s)) {
                        s = s.substring(1);
                    }
                    int en = indexes.get(s);
                    if (!prefixesIsTerminal.get(en)) {
                        update(i, st, en, 1L);
                    }
                }
            }
        }

        while (true) {
            Val current = q.pollFirst();
            if (current == null) {
                break;
            }
            int i = current.i;
            int st = current.st;
            int en = current.en;
            long cur = current.value;

            for (int pos = mutationsByRhsSt[i]; pos < mutationsByRhsSt[i + 1]; pos++) {
                int ind = mutationsByRhs[pos];
                Mutation mutation = mutations.get(ind);
                if (mutation.en2 == null) {
                    update(mutation.st, st, en, cur);
                } else {
                    if (mutation.en1 == i) {
                        for (int md = 0; md < S; md++) {
                            update(mutation.st, st, md, cur + get(mutation.en2, en, md));
                        }
                    }
                    if (mutation.en2 == i) {
                        for (int md = 0; md < S; md++) {
                            update(mutation.st, md, en, get(mutation.en1, md, st) + cur);
                        }
                    }
                }
            }
        }

        for (int i = 2; i < origG; i++) {
            long res = MYINFLL;
            for (int en = 0; en < S; en++) {
                long cur = get(i, 0, en);
                if (cur < res) {
                    res = cur;
                }
            }
            if (res == MYINFLL) {
                bw.write("YES\n");
            } else {
                bw.write("NO ");
                bw.write(String.valueOf(res));
                bw.write("\n");
            }
        }

        bw.close();
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...