Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.*;
- class Position {
- public Position(double x, double y) {
- this.x = x;
- this.y = y;
- }
- public double x;
- public double y;
- public double distanceFrom(Position p2) {
- return (x - p2.x) * (x - p2.x) + (y - p2.y) * (y - p2.y);
- }
- }
- class Entity {
- public int id;
- }
- class Topic extends Entity {
- public Position pos;
- }
- class Question extends Entity {
- public List<Integer> topics;
- public Question() {
- topics = new ArrayList<Integer>();
- }
- }
- class Rectangle {
- public double left;
- public double right;
- public double up;
- public double down;
- public Rectangle(double left, double right, double up, double down) {
- this.left = left;
- this.right = right;
- this.up = up;
- this.down = down;
- }
- public boolean intersects(Rectangle rect) {
- boolean intersectsX = !(rect.left > right || rect.right < left);
- boolean intersectsY = !(rect.down > up || rect.up < down);
- return intersectsX && intersectsY;
- }
- }
- class QuadTree {
- private static final int MAX_LEVEL = 8;
- private List<Topic> topicList;
- private Rectangle rect;
- private Position center;
- private QuadTree nw, ne, sw, se;
- private static List<Topic> obtainedTopics;
- public QuadTree() {
- }
- public List<Topic> getTopicsInCircle(Position o, double radius) {
- obtainedTopics = new ArrayList<Topic>();
- Rectangle requiredRect = new Rectangle(o.x - radius, o.x + radius, o.y + radius, o.y - radius);
- getTopicsInCircle(o, radius, requiredRect);
- return obtainedTopics;
- }
- private void getTopicsInCircle(Position o, double radius, Rectangle requiredRect) {
- if (topicList != null) {
- for (Topic t : topicList) {
- double dist = o.distanceFrom(t.pos);
- if (dist <= radius*radius) {
- obtainedTopics.add(t);
- }
- }
- }
- addInRange(nw, o, radius, requiredRect);
- addInRange(ne, o, radius, requiredRect);
- addInRange(sw, o, radius, requiredRect);
- addInRange(se, o, radius, requiredRect);
- }
- private void addInRange(QuadTree qt, Position o, double radius, Rectangle requiredRect) {
- if (qt != null) {
- if (qt.rect.intersects(requiredRect)) {
- qt.getTopicsInCircle(o, radius, requiredRect);
- }
- }
- }
- public void addTopics(List<Topic> topics, Rectangle bounding, int level) {
- if (topics.size() == 0) {
- return;
- }
- if (bounding == null){
- rect = buildRect(topics);
- } else {
- rect = bounding;
- }
- center = new Position((rect.left + rect.right) / 2.0, (rect.down + rect.up) / 2.0);
- if (level > MAX_LEVEL) {
- this.topicList = topics;
- return;
- }
- Rectangle nwRect = initRectangle();
- List<Topic> nwTopics = new ArrayList<Topic>();
- Rectangle neRect = initRectangle();
- List<Topic> neTopics = new ArrayList<Topic>();
- Rectangle swRect = initRectangle();
- List<Topic> swTopics = new ArrayList<Topic>();
- Rectangle seRect = initRectangle();
- List<Topic> seTopics = new ArrayList<Topic>();
- for (int i = 0; i < topics.size(); i++) {
- Position pos = topics.get(i).pos;
- if (pos.x < center.x && pos.y < center.y) {
- updateRectangle(swRect, pos);
- swTopics.add(topics.get(i));
- } else if (pos.x < center.x && pos.y > center.y) {
- updateRectangle(nwRect, pos);
- nwTopics.add(topics.get(i));
- } else if (pos.x > center.x && pos.y > center.y) {
- updateRectangle(neRect, pos);
- neTopics.add(topics.get(i));
- } else {
- updateRectangle(seRect, pos);
- seTopics.add(topics.get(i));
- }
- }
- // add the necessary sub quadtrees
- nw = assignTopics(nwTopics, nwRect, level);
- ne = assignTopics(neTopics, neRect, level);
- sw = assignTopics(swTopics, swRect, level);
- se = assignTopics(seTopics, seRect, level);
- }
- private void updateRectangle(Rectangle rect, Position pos){
- if (pos.x > rect.right) {
- rect.right = pos.x;
- }
- if (pos.x < rect.left) {
- rect.left = pos.x;
- }
- if (pos.y > rect.up) {
- rect.up = pos.y;
- }
- if (pos.y < rect.down) {
- rect.down = pos.y;
- }
- }
- private Rectangle initRectangle(){
- return new Rectangle(Double.MAX_VALUE, Double.MIN_VALUE,Double.MIN_VALUE, Double.MAX_VALUE);
- }
- QuadTree assignTopics(List<Topic> topics, Rectangle rect, int level) {
- if (topics.size() > 0) {
- QuadTree qt = new QuadTree();
- qt.addTopics(topics, rect, level+1);
- return qt;
- }
- return null;
- }
- private Rectangle buildRect(List<Topic> topics) {
- double left = Double.MAX_VALUE, right = Double.MIN_VALUE, up = Double.MIN_VALUE, down = Double.MAX_VALUE;
- for (int i = 0; i < topics.size(); i++) {
- Position pos = topics.get(i).pos;
- if (pos.x > right) {
- right = pos.x;
- }
- if (pos.x < left) {
- left = pos.x;
- }
- if (pos.y > up) {
- up = pos.y;
- }
- if (pos.y < down) {
- down = pos.y;
- }
- }
- return new Rectangle(left, right, up, down);
- }
- }
- public class Solution {
- private static final double INITIAL_RADIUS = 1.0;
- private static final double RADIUS_MULTIPLIER = 2.0;
- private static final double EPSILON = 0.000001;
- private static int t, q, n;
- private static List<Topic> topics;
- private static List<Question> questions;
- private static Map<Integer, List<Question>> topicMap;
- private static QuadTree qt;
- public static void main(String[] args) throws Exception {
- Scanner scanner = new Scanner(System.in);
- initData();
- readData(scanner);
- createQuadTree();
- solveQueries(scanner);
- }
- private static void createQuadTree() {
- qt = new QuadTree();
- qt.addTopics(topics, null, 0);
- }
- private static void readData(Scanner scanner) {
- t = scanner.nextInt();
- q = scanner.nextInt();
- n = scanner.nextInt();
- readTopics(scanner, t);
- readQuestions(scanner, q);
- }
- private static void readTopics(Scanner scanner, int t) {
- for (int i = 0; i < t; i++) {
- int id = scanner.nextInt();
- double x = scanner.nextDouble();
- double y = scanner.nextDouble();
- Topic topic = new Topic();
- topic.id = id;
- Position pos = new Position(x, y);
- topic.pos = pos;
- topics.add(topic);
- }
- }
- private static void readQuestions(Scanner scanner, int q) {
- for (int i = 0; i < q; i++) {
- int id = scanner.nextInt();
- int qn = scanner.nextInt();
- if (qn > 0) {
- Question question = new Question();
- question.id = id;
- for (int j = 0; j < qn; j++) {
- int topicId = scanner.nextInt();
- addToMap(topicId, question);
- }
- questions.add(question);
- }
- }
- }
- private static void addToMap(int topicId, Question question){
- if (!topicMap.containsKey(topicId)){
- topicMap.put(topicId, new ArrayList<Question>());
- }
- topicMap.get(topicId).add(question);
- }
- private static void solveQueries(Scanner scanner) throws Exception {
- for (int i = 0; i < n; i++) {
- String queryType = null;
- do {
- queryType = scanner.next();
- } while (!queryType.equals("t") && !queryType.equals("q"));
- int resultsNr = scanner.nextInt();
- double targetX = scanner.nextDouble();
- double targetY = scanner.nextDouble();
- int[] sol;
- if (resultsNr > 0) {
- if (queryType.equals("t")) {
- sol = queryClosestTopics(resultsNr, targetX, targetY);
- } else {
- sol = queryClosestQuestions(resultsNr, targetX, targetY);
- }
- printSol(sol);
- } else {
- System.out.println();
- }
- }
- }
- private static void printSol(int[] sol) {
- for (int i = 0; i < sol.length; i++) {
- System.out.print(sol[i] + " ");
- }
- System.out.println();
- }
- private static int[] queryClosestTopics(int nr, double x, double y) {
- double currRadius = INITIAL_RADIUS;
- int reqTopics = Math.min(nr, topics.size());
- List<Topic> topicsInRange = null;
- final Position center = new Position(x, y);
- do {
- topicsInRange = qt.getTopicsInCircle(center, currRadius);
- currRadius *= RADIUS_MULTIPLIER;
- } while (topicsInRange.size() < reqTopics);
- Collections.sort(topicsInRange, new Comparator<Topic>() {
- @Override
- public int compare(Topic t1, Topic t2) {
- double dist1 = center.distanceFrom(t1.pos);
- double dist2 = center.distanceFrom(t2.pos);
- if (Math.abs(dist1-dist2) < EPSILON){
- return -((Integer)t1.id).compareTo(t2.id);
- } else if (dist1 < dist2){
- return -1;
- } else {
- return 1;
- }
- }
- });
- return obtainSolution(topicsInRange, reqTopics);
- }
- private static int[] queryClosestQuestions(int nr, final double x, final double y) {
- double currRadius = INITIAL_RADIUS;
- Map<Question, Double> questionMap = new HashMap<Question, Double>();
- List<Topic> topicsInRange = null;
- final Position center = new Position(x, y);
- do {
- topicsInRange = qt.getTopicsInCircle(center, currRadius);
- questionMap = createQuestionMap(topicsInRange, center);
- currRadius *= RADIUS_MULTIPLIER;
- } while (questionMap.keySet().size() < nr && topicsInRange.size() < t);
- ArrayList<Map.Entry<Question, Double>> entityTupleList = new ArrayList<Map.Entry<Question, Double>>();
- entityTupleList.addAll(questionMap.entrySet());
- Collections.sort(entityTupleList, new Comparator<Map.Entry<Question, Double>>() {
- public int compare(Map.Entry<Question, Double> e1, Map.Entry<Question, Double> e2) {
- double dist1 = e1.getValue();
- double dist2 = e2.getValue();
- if (Math.abs(dist1-dist2) < EPSILON){
- return -((Integer)e1.getKey().id).compareTo(e2.getKey().id);
- } else if (dist1 < dist2){
- return -1;
- } else {
- return 1;
- }
- }
- });
- return obtainQuestionSolution(entityTupleList, Math.min(nr, entityTupleList.size()));
- }
- private static int[] obtainQuestionSolution(List<Map.Entry<Question, Double>> entityTuples, int nr){
- int[] sol = new int[nr];
- for (int i=0; i<nr; i++){
- sol[i] = entityTuples.get(i).getKey().id;
- }
- return sol;
- }
- private static Map<Question, Double> createQuestionMap(List<Topic> topicsInRange, Position center){
- Map<Question, Double> questionMap = new HashMap<Question, Double>();
- if (topicsInRange != null){
- for (Topic topic:topicsInRange){
- if (topicMap.containsKey(topic.id)){
- for (Question q :topicMap.get(topic.id)){
- double dist = center.distanceFrom(topic.pos);
- if (questionMap.containsKey(q)){
- if (questionMap.get(q) > dist ){
- questionMap.put(q, dist);
- }
- } else {
- questionMap.put(q, dist);
- }
- }
- }
- }
- }
- return questionMap;
- }
- private static int[] obtainSolution(List<? extends Entity> l, int size) {
- int[] sol = new int[size];
- for (int i=0; i<size; i++){
- sol[i] = l.get(i).id;
- }
- return sol;
- }
- private static void initData() {
- topicMap = new HashMap<Integer, List<Question>>();
- topics = new ArrayList<Topic>();
- questions = new ArrayList<Question>();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement