算法训练 会议中心

ALGO-40 会议中心

资源限制

时间限制:2.0s 内存限制:512.0MB

问题描述

会议中心  Siruseri政府建造了一座新的会议中心。许多公司对租借会议中心的会堂很感兴趣,他们希望能够在里面举行会议。
对于一个客户而言,仅当在开会时能够独自占用整个会堂,他才会租借会堂。会议中心的销售主管认为:最好的策略应该是将会堂租借给尽可能多的客户。显然,有可能存在不止一种满足要求的策略。
例如下面的例子。总共有4个公司。他们对租借会堂发出了请求,并提出了他们所需占用会堂的起止日期(如下表所示)。

 开始日期结束日期
公司149
公司2911
公司31319
公司41017

上例中,最多将会堂租借给两家公司。租借策略分别是租给公司1和公司3,或是公司2和公司3,也可以是公司1和公司4。注意会议中心一天最多租借给一个公司,所以公司1和公司2不能同时租借会议中心,因为他们在第九天重合了。
销售主管为了公平起见,决定按照如下的程序来确定选择何种租借策略:首先,将租借给客户数量最多的策略作为候选,将所有的公司按照他们发出请求的顺序编号。对于候选策略,将策略中的每家公司的编号按升序排列。最后,选出其中字典序最小[1]的候选策略作为最终的策略。
例中,会堂最终将被租借给公司1和公司3:3个候选策略是{(1,3),(2,3),(1,4)}。而在字典序中(1,3)<(1,4)<(2,3)。
你的任务是帮助销售主管确定应该将会堂租借给哪些公司。

输入格式

输入的第一行有一个整数N,表示发出租借会堂申请的公司的个数。第2到第N+1行每行有2个整数。第i+1行的整数表示第i家公司申请租借的起始和终止日期。对于每个公司的申请,起始日期为不小于1的整数,终止日期为不大于109的整数。

输出格式

输出的第一行应有一个整数M,表示最多可以租借给多少家公司。第二行应列出M个数,表示最终将会堂租借给哪些公司。

测试样例

输入:
4
4 9
9 11
13 19
10 17

输出:
2
1 3

数据规模与约定

对于50%的输入,N≤3000。在所有输入中,N≤200000。

AC code:

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

public class Main {

    static int f[][], cases = 1;
    static Node[] cas;

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in, " \n");
        PrintWriter out = new PrintWriter(System.out);
        int n = in.nextInt() + 1;
        f = new int[n][21];
        cas = new Node[n + 1];
        Node[] arr = new Node[n];
        for (int i = 1; i < n; i++) arr[i] = cas[i] = new Node(i, in.nextInt(), in.nextInt());
        Arrays.sort(cas, 1, n);
        for (int i = 1; i < n; i++) if (cas[cases].begin < cas[i].begin) cas[++cases] = cas[i];
        cas[cases + 1] = new Node(0, Integer.MAX_VALUE, 0);
        for (int i = 1, j = 1; i <= cases; j = ++i) {
            while (cas[j].begin <= cas[i].end) j++;
            if (j <= cases) f[i][0] = j;
        }
        for (int j = 1; j <= 20; j++)
            for (int i = 1; i <= cases; i++) f[i][j] = f[f[i][j - 1]][j - 1];
        out.println(calcCnt(0, Integer.MAX_VALUE));
        Tree<Node> tree = new Tree(new Node(0), new Node(1000000000));
        for (int i = 1; i < n; i++) {
            Comparable[] cont = tree.search(arr[i]);
            int l = ((Node)cont[0]).end, r = ((Node)cont[1]).begin;
            if (l >= arr[i].begin || r <= arr[i].end) continue;
            if (calcCnt(l + 1, r - 1) == calcCnt(l + 1, arr[i].begin - 1) + calcCnt(arr[i].end + 1, r - 1) + 1) {
                tree.insert(arr[i]);
                out.print(i + " ");
            }
        }
        out.close();
    }

    static int calcCnt(int begin, int end) {
        int res = 1, now = search(begin);
        if (now > cases || cas[now].end > end) return 0;
        for (int i = 20; i >= 0; i--)
            if (f[now][i] > 0 && cas[f[now][i]].end <= end) {
                now = f[now][i];
                res += 1 << i;
            }
        return res;
    }

    static int search(int begin) {
        int left = 1, right = cases;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            if (cas[mid].begin >  begin) right = mid - 1;
            else if (cas[mid].begin <  begin) left = mid + 1;
            else return mid;
        }
        return right + 1;
    }

    static class Node implements Comparable<Node> {
        int begin;
        int end;
        int id;

        Node(int feel) {this.id = this.end = this.begin = feel;}

        Node(int id, int begin, int end) {
            this.id = id;
            this.end = end;
            this.begin = begin;
        }

        public int compareTo(Node t) { return this.end == t.end? t.begin - this.begin: this.end - t.end; }
    }

    static class Tree<T extends Comparable<T>> {

        final boolean RED = true;
        final boolean BLACK = false;

        Node root;

        class Node {
            T value;
            Node left;
            Node right;
            boolean color;

            Node(T value, boolean color) {
                this.value = value;
                this.color = color;
            }
        }

        Tree(T MINValue, T MAXValue) {
            root = new Node(MAXValue, BLACK);
            root.left = new Node(MINValue, RED);
        }

        void insert(T value) {
            root = insert(root, value);
            root.color = BLACK;
        }

        Comparable[] search(T node) {
            Comparable[] res = new Comparable[2];
            search(root, node, res);
            return res;
        }

        void search(Node root, T node, Comparable[] res) {
            if (root.value.compareTo(node) > 0) {
                res[1] = root.value;
                if (root.left != null) search(root.left, node, res);
            } else {
                res[0] = root.value;
                if (root.right != null) search(root.right, node, res);
            }
        }

        Node insert(Node root, T value) {
            if (root == null) return new Node(value, RED);
            if (root.value.compareTo(value) > 0) root.left = insert(root.left, value);
            else root.right = insert(root.right, value);
            if (isRed(root.right) && !isRed(root.left)) root = rotateLeft(root);
            if (isRed(root.left) && isRed(root.left.left)) root = rotateRight(root);
            if (isRed(root.left) && isRed(root.right)) flipColor(root);
            return root;
        }

        boolean isRed(Node x) {
            if (x == null) return false;
            return x.color;
        }

        void flipColor(Node h) {
            h.color = RED;
            h.left.color = BLACK;
            h.right.color = BLACK;
        }

        Node rotateLeft(Node h) {
            Node x = h.right;
            h.right = x.left;
            x.left = h;
            x.color = h.color;
            h.color = RED;
            return x;
        }

        Node rotateRight(Node h) {
            Node x = h.left;
            h.left = x.right;
            x.right = h;
            x.color = h.color;
            h.color = RED;
            return x;
        }
    }

    static class InputReader {

        BufferedReader read;
        StringTokenizer token;
        String delimiters;

        InputReader(InputStream in) { this(in, " \t\n\r\f"); }

        InputReader(InputStream in, String delimiters) {
            this.read = new BufferedReader(new InputStreamReader(in));
            this.token = new StringTokenizer("", this.delimiters = delimiters);
        }

        String next() {
            while (!token.hasMoreTokens())
                try {
                    this.token = new StringTokenizer(read.readLine(), delimiters);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return token.nextToken();
        }

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

参考
人写麻了


人看麻了,APIO的题跟蓝桥自己的题根本就不是一个层次的
先按自己的理解跑一遍:

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

public class Main {

    static int[] plans;
    static Times[] times;

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in, " \n");
        PrintWriter out = new PrintWriter(System.out);
        int n = in.nextInt() + 1, max = 0, end = n;
        plans = new int[n];
        times = new Times[n];
        int[] dpLen = new int[n];
        for (int i = 1;i < n; i++) times[i] = new Times(i, in.nextInt(), in.nextInt());
        Arrays.sort(times, 1, n);
        for (int i = 1; i < n; i++) {
            for (int j  = 1; j < i; j++)
                if (times[i].begin > times[j].end)
                    if (dpLen[j] > dpLen[i]) dpLen[i] = dpLen[plans[i] = j];
                    else if (dpLen[j] == dpLen[i] && consult(plans[i], j)) plans[i] = j;
            if (++dpLen[i] == 1) plans[i] = 0;
            if (dpLen[i] > max) max = dpLen[end = i];
            else if (dpLen[i] == max && times[i].id < times[end].id) end = i;
        }
        out.println(max);
        Queue<Integer> queue = new PriorityQueue();
        while (end != 0) {
            queue.offer(times[end].id);
            end = plans[end];
        }
        while (queue.size() > 0) out.print(queue.poll() + " ");
        out.close();
    }

    static boolean consult(int i, int j) {
        Queue<Integer> queue1 = new PriorityQueue();
        Queue<Integer> queue2 = new PriorityQueue();
        while (i != 0) { queue1.offer(times[i].id); i = plans[i]; }
        while (j != 0) { queue2.offer(times[j].id); j = plans[j]; }
        while (queue1.size() > 0) if (queue1.poll() > queue2.poll()) return true;
        return false;
    }

    static class Times implements Comparable<Times> {
        int begin;
        int end;
        int id;

        Times(int id, int begin, int end) {
            this.id = id;
            this.end = end;
            this.begin = begin;
        }

        @Override
        public int compareTo(Times t) {
            return this.begin - t.begin;
        }
    }

    static class InputReader {

        BufferedReader read;
        StringTokenizer token;
        String delimiters;

        InputReader(InputStream in) { this(in, " \t\n\r\f"); }

        InputReader(InputStream in, String delimiters) {
            this.read = new BufferedReader(new InputStreamReader(in));
            this.token = new StringTokenizer("", this.delimiters = delimiters);
        }

        String next() {
            while (!token.hasMoreTokens())
                try {
                    this.token = new StringTokenizer(read.readLine(), delimiters);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return token.nextToken();
        }

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

在这里插入图片描述
如果在字典序比较时,把最小值保存起来,如果最小值相等,再遍历出路径进行比较的话
可能可以到 1s 内,但这样内存就超过了 512.0MB 的限制,大概

先去吃个饭

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值