Java solution using heap and sorted set.
We use 2 data structures that together answer the main question (faster compared to linear scan):\nWhich server with smallest id with ceiling i%k is available a
We use 2 data structures that together answer the main question (faster compared to linear scan):\n*Which server with **smallest id with ceiling i%k** is **available** at time arrival[i]?*\n\n1. **availability** can be answered by Min heap ordered by end time of each server called busy.\n2. **smalled id with ceiling i%k** can be answered by sorted set ordered by server id called free.\n\nWhile iterating over the loads:\n1. move free servers from busy to free at arrival[i] (server.freeAt <= arrival[i])\n2. query free servers to return smallest id after i%k (if none, get smallet id after 0).\n3. update freeAt and move server from free to busy.\n\nKeep track of maxServer handled and add to the return list accodingly.\n \n```\nclass Solution {\n    \n    static class Server {\n        int id;\n        int freeAt;\n        int tasksHandled;\n        \n        public Server(int id, int freeAt) {\n            this.id = id;\n            this.freeAt = freeAt;\n        }\n        \n        public boolean equals(Object o) {\n            Server s = (Server) o;\n            return s.id == this.id;\n        }\n        \n        public int hashCode() {\n            return this.id;\n        }\n    }\n    \n    public List<Integer> busiestServers(int k, int[] arrival, int[] load) {\n        TreeSet<Server> free = new TreeSet<Server>((x, y) -> {return x.id - y.id;});\n        PriorityQueue<Server> busy = new PriorityQueue<Server>((x, y) -> {return x.freeAt - y.freeAt;});\n        \n        int maxHandled = 0;\n        List<Integer> maxHandleServers = null;\n        \n        for(int i=0; i<k; i++) free.add(new Server(i, 0));\n        \n        for(int i=0; i<arrival.length; i++) {\n            while(!busy.isEmpty() && busy.peek().freeAt <= arrival[i]) {\n                free.add(busy.poll());\n            }\n            \n            if(free.isEmpty()) continue;\n            \n            Server freeServer = free.ceiling(new Server(i%k, 0));\n            if(freeServer == null) freeServer = free.first();\n            \n            freeServer.freeAt = arrival[i] + load[i];\n            freeServer.tasksHandled++;\n            \n            if(freeServer.tasksHandled > maxHandled) {\n                maxHandled = freeServer.tasksHandled;\n                maxHandleServers = new ArrayList();\n                maxHandleServers.add(freeServer.id);\n            } else if(freeServer.tasksHandled == maxHandled) {\n                maxHandleServers.add(freeServer.id);\n            }\n            \n            free.remove(freeServer);\n            busy.add(freeServer);\n        }\n        \n        return maxHandleServers;\n    }\n}\n```
['Heap (Priority Queue)']