Java O(nlogn) + O(nlogk) with explaination and comment.
The idea is simulating the whole process. For the time when a job start and a end, we create a event, and sort these events. \n\nJava\nclass Solution {\n    pub
The idea is simulating the whole process. For the time when a job start and a end, we create a event, and sort these events. \n\n```Java\nclass Solution {\n    public List<Integer> busiestServers(int k, int[] a, int[] l) {\n        TreeSet<Integer> servers = new TreeSet<>();  // the set stores availabe servers \n        for (int i = 0; i < k; i++) {\n            servers.add(i);\n        }\n        int[] jobs = new int[k];   // jobs[i] stores how many job ith server finished so far\n        List<Event> events = new ArrayList<>();\n        for (int i = 0; i < a.length; i++) {\n            events.add(new Event(i, 1, a[i]));\n            events.add(new Event(i, 0, a[i] + l[i]));\n        }\n        Collections.sort(events, (e1, e2) -> {\n            return e1.time == e2.time ? e1.time - e2.time : e1.time - e2.time;   // we sort the the event by \n\t\t\t// the time stamp, when the timestamp is same, we put the ending event first, so we can free the server as soon as possible.\n        });\n        Map<Integer, Integer> idToServer = new HashMap<>();   // this stores mapping between job.id and server\n        for (Event event : events) {\n            if (event.start == 1) {\n                if (servers.isEmpty()) {   // if no available server, we have to drop the job\n                    continue;\n                } else {\n                    int server = nextServer(servers, event.id % k); // find next available server \n                    idToServer.put(event.id, server);      // recording the mapping\n                    jobs[server]++;\n                    servers.remove(server);\n                }\n            } else {\n                Integer server = idToServer.get(event.id);   // if server == null means the job was dropped.\n                if (server != null) {\n                    servers.add(server);    // add the server back to available servers.\n                }\n            }\n        }\n        int max = IntStream.of(jobs).max().getAsInt();\n        List<Integer> ans = new ArrayList<>();\n        for (int i = 0; i < jobs.length; i++) {\n            if (jobs[i] == max) {\n                ans.add(i);\n            }\n        }\n        return ans;\n    }\n    \n    int nextServer(TreeSet<Integer> servers, int id) {\n        Integer nextServer = servers.ceiling(id);\n        return nextServer != null ? nextServer : servers.first();\n    }\n    \n    \n    public static class Event {\n        \n        public int start; // 1 start 0 end\n        \n        public int time;\n        \n        public int id;\n        \n        public Event(int id, int start, int time) {\n            this.start = start;\n            this.time = time;\n            this.id = id;\n        }\n    }\n}\n\n```
[]