Advertisement
Guest User

Untitled

a guest
Oct 31st, 2014
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.11 KB | None | 0 0
  1. import java.util.*;
  2.  
  3.  
  4. class Position {
  5.  
  6. public Position(double x, double y) {
  7. this.x = x;
  8. this.y = y;
  9. }
  10.  
  11. public double x;
  12. public double y;
  13.  
  14. public double distanceFrom(Position p2) {
  15. return (x - p2.x) * (x - p2.x) + (y - p2.y) * (y - p2.y);
  16. }
  17. }
  18.  
  19. class Entity {
  20. public int id;
  21. }
  22.  
  23. class Topic extends Entity {
  24. public Position pos;
  25. }
  26.  
  27. class Question extends Entity {
  28. public List<Integer> topics;
  29.  
  30. public Question() {
  31. topics = new ArrayList<Integer>();
  32. }
  33. }
  34.  
  35. class Rectangle {
  36. public double left;
  37. public double right;
  38. public double up;
  39. public double down;
  40.  
  41. public Rectangle(double left, double right, double up, double down) {
  42. this.left = left;
  43. this.right = right;
  44. this.up = up;
  45. this.down = down;
  46. }
  47.  
  48. public boolean intersects(Rectangle rect) {
  49. boolean intersectsX = !(rect.left > right || rect.right < left);
  50. boolean intersectsY = !(rect.down > up || rect.up < down);
  51.  
  52. return intersectsX && intersectsY;
  53. }
  54. }
  55.  
  56. class QuadTree {
  57.  
  58. private static final int MAX_LEVEL = 8;
  59. private List<Topic> topicList;
  60. private Rectangle rect;
  61. private Position center;
  62.  
  63. private QuadTree nw, ne, sw, se;
  64. private static List<Topic> obtainedTopics;
  65.  
  66. public QuadTree() {
  67. }
  68.  
  69.  
  70. public List<Topic> getTopicsInCircle(Position o, double radius) {
  71. obtainedTopics = new ArrayList<Topic>();
  72. Rectangle requiredRect = new Rectangle(o.x - radius, o.x + radius, o.y + radius, o.y - radius);
  73. getTopicsInCircle(o, radius, requiredRect);
  74.  
  75. return obtainedTopics;
  76. }
  77.  
  78. private void getTopicsInCircle(Position o, double radius, Rectangle requiredRect) {
  79.  
  80. if (topicList != null) {
  81. for (Topic t : topicList) {
  82. double dist = o.distanceFrom(t.pos);
  83. if (dist <= radius*radius) {
  84. obtainedTopics.add(t);
  85. }
  86. }
  87. }
  88.  
  89.  
  90. addInRange(nw, o, radius, requiredRect);
  91. addInRange(ne, o, radius, requiredRect);
  92. addInRange(sw, o, radius, requiredRect);
  93. addInRange(se, o, radius, requiredRect);
  94. }
  95.  
  96. private void addInRange(QuadTree qt, Position o, double radius, Rectangle requiredRect) {
  97. if (qt != null) {
  98. if (qt.rect.intersects(requiredRect)) {
  99. qt.getTopicsInCircle(o, radius, requiredRect);
  100. }
  101. }
  102. }
  103.  
  104. public void addTopics(List<Topic> topics, Rectangle bounding, int level) {
  105. if (topics.size() == 0) {
  106. return;
  107. }
  108.  
  109. if (bounding == null){
  110. rect = buildRect(topics);
  111. } else {
  112. rect = bounding;
  113. }
  114.  
  115. center = new Position((rect.left + rect.right) / 2.0, (rect.down + rect.up) / 2.0);
  116.  
  117. if (level > MAX_LEVEL) {
  118. this.topicList = topics;
  119. return;
  120. }
  121.  
  122. Rectangle nwRect = initRectangle();
  123. List<Topic> nwTopics = new ArrayList<Topic>();
  124.  
  125. Rectangle neRect = initRectangle();
  126. List<Topic> neTopics = new ArrayList<Topic>();
  127.  
  128. Rectangle swRect = initRectangle();
  129. List<Topic> swTopics = new ArrayList<Topic>();
  130.  
  131. Rectangle seRect = initRectangle();
  132. List<Topic> seTopics = new ArrayList<Topic>();
  133.  
  134. for (int i = 0; i < topics.size(); i++) {
  135. Position pos = topics.get(i).pos;
  136.  
  137. if (pos.x < center.x && pos.y < center.y) {
  138. updateRectangle(swRect, pos);
  139. swTopics.add(topics.get(i));
  140. } else if (pos.x < center.x && pos.y > center.y) {
  141. updateRectangle(nwRect, pos);
  142. nwTopics.add(topics.get(i));
  143. } else if (pos.x > center.x && pos.y > center.y) {
  144. updateRectangle(neRect, pos);
  145. neTopics.add(topics.get(i));
  146. } else {
  147. updateRectangle(seRect, pos);
  148. seTopics.add(topics.get(i));
  149. }
  150. }
  151.  
  152.  
  153. // add the necessary sub quadtrees
  154. nw = assignTopics(nwTopics, nwRect, level);
  155. ne = assignTopics(neTopics, neRect, level);
  156. sw = assignTopics(swTopics, swRect, level);
  157. se = assignTopics(seTopics, seRect, level);
  158. }
  159.  
  160. private void updateRectangle(Rectangle rect, Position pos){
  161. if (pos.x > rect.right) {
  162. rect.right = pos.x;
  163. }
  164.  
  165. if (pos.x < rect.left) {
  166. rect.left = pos.x;
  167. }
  168.  
  169. if (pos.y > rect.up) {
  170. rect.up = pos.y;
  171. }
  172.  
  173. if (pos.y < rect.down) {
  174. rect.down = pos.y;
  175. }
  176. }
  177.  
  178. private Rectangle initRectangle(){
  179. return new Rectangle(Double.MAX_VALUE, Double.MIN_VALUE,Double.MIN_VALUE, Double.MAX_VALUE);
  180. }
  181.  
  182. QuadTree assignTopics(List<Topic> topics, Rectangle rect, int level) {
  183. if (topics.size() > 0) {
  184. QuadTree qt = new QuadTree();
  185. qt.addTopics(topics, rect, level+1);
  186. return qt;
  187. }
  188.  
  189. return null;
  190. }
  191.  
  192. private Rectangle buildRect(List<Topic> topics) {
  193. double left = Double.MAX_VALUE, right = Double.MIN_VALUE, up = Double.MIN_VALUE, down = Double.MAX_VALUE;
  194.  
  195.  
  196. for (int i = 0; i < topics.size(); i++) {
  197. Position pos = topics.get(i).pos;
  198.  
  199. if (pos.x > right) {
  200. right = pos.x;
  201. }
  202.  
  203. if (pos.x < left) {
  204. left = pos.x;
  205. }
  206.  
  207. if (pos.y > up) {
  208. up = pos.y;
  209. }
  210.  
  211. if (pos.y < down) {
  212. down = pos.y;
  213. }
  214. }
  215.  
  216. return new Rectangle(left, right, up, down);
  217. }
  218.  
  219. }
  220.  
  221.  
  222. public class Solution {
  223.  
  224. private static final double INITIAL_RADIUS = 1.0;
  225. private static final double RADIUS_MULTIPLIER = 2.0;
  226. private static final double EPSILON = 0.000001;
  227.  
  228. private static int t, q, n;
  229. private static List<Topic> topics;
  230. private static List<Question> questions;
  231. private static Map<Integer, List<Question>> topicMap;
  232. private static QuadTree qt;
  233.  
  234. public static void main(String[] args) throws Exception {
  235. Scanner scanner = new Scanner(System.in);
  236.  
  237. initData();
  238. readData(scanner);
  239.  
  240. createQuadTree();
  241. solveQueries(scanner);
  242. }
  243.  
  244. private static void createQuadTree() {
  245. qt = new QuadTree();
  246. qt.addTopics(topics, null, 0);
  247. }
  248.  
  249.  
  250. private static void readData(Scanner scanner) {
  251. t = scanner.nextInt();
  252. q = scanner.nextInt();
  253. n = scanner.nextInt();
  254.  
  255. readTopics(scanner, t);
  256. readQuestions(scanner, q);
  257. }
  258.  
  259. private static void readTopics(Scanner scanner, int t) {
  260.  
  261. for (int i = 0; i < t; i++) {
  262. int id = scanner.nextInt();
  263. double x = scanner.nextDouble();
  264. double y = scanner.nextDouble();
  265.  
  266. Topic topic = new Topic();
  267. topic.id = id;
  268. Position pos = new Position(x, y);
  269. topic.pos = pos;
  270.  
  271. topics.add(topic);
  272. }
  273.  
  274. }
  275.  
  276. private static void readQuestions(Scanner scanner, int q) {
  277.  
  278. for (int i = 0; i < q; i++) {
  279. int id = scanner.nextInt();
  280. int qn = scanner.nextInt();
  281.  
  282. if (qn > 0) {
  283. Question question = new Question();
  284. question.id = id;
  285.  
  286. for (int j = 0; j < qn; j++) {
  287. int topicId = scanner.nextInt();
  288. addToMap(topicId, question);
  289. }
  290.  
  291. questions.add(question);
  292. }
  293. }
  294.  
  295. }
  296.  
  297. private static void addToMap(int topicId, Question question){
  298. if (!topicMap.containsKey(topicId)){
  299. topicMap.put(topicId, new ArrayList<Question>());
  300. }
  301.  
  302. topicMap.get(topicId).add(question);
  303. }
  304.  
  305. private static void solveQueries(Scanner scanner) throws Exception {
  306. for (int i = 0; i < n; i++) {
  307. String queryType = null;
  308.  
  309. do {
  310. queryType = scanner.next();
  311. } while (!queryType.equals("t") && !queryType.equals("q"));
  312.  
  313. int resultsNr = scanner.nextInt();
  314. double targetX = scanner.nextDouble();
  315. double targetY = scanner.nextDouble();
  316.  
  317.  
  318. int[] sol;
  319.  
  320. if (resultsNr > 0) {
  321. if (queryType.equals("t")) {
  322. sol = queryClosestTopics(resultsNr, targetX, targetY);
  323. } else {
  324. sol = queryClosestQuestions(resultsNr, targetX, targetY);
  325. }
  326.  
  327. printSol(sol);
  328. } else {
  329. System.out.println();
  330. }
  331.  
  332. }
  333.  
  334. }
  335.  
  336. private static void printSol(int[] sol) {
  337. for (int i = 0; i < sol.length; i++) {
  338. System.out.print(sol[i] + " ");
  339. }
  340.  
  341. System.out.println();
  342. }
  343.  
  344. private static int[] queryClosestTopics(int nr, double x, double y) {
  345. double currRadius = INITIAL_RADIUS;
  346. int reqTopics = Math.min(nr, topics.size());
  347. List<Topic> topicsInRange = null;
  348.  
  349. final Position center = new Position(x, y);
  350.  
  351. do {
  352. topicsInRange = qt.getTopicsInCircle(center, currRadius);
  353. currRadius *= RADIUS_MULTIPLIER;
  354. } while (topicsInRange.size() < reqTopics);
  355.  
  356.  
  357. Collections.sort(topicsInRange, new Comparator<Topic>() {
  358. @Override
  359. public int compare(Topic t1, Topic t2) {
  360. double dist1 = center.distanceFrom(t1.pos);
  361. double dist2 = center.distanceFrom(t2.pos);
  362.  
  363. if (Math.abs(dist1-dist2) < EPSILON){
  364. return -((Integer)t1.id).compareTo(t2.id);
  365. } else if (dist1 < dist2){
  366. return -1;
  367. } else {
  368. return 1;
  369. }
  370. }
  371. });
  372.  
  373.  
  374. return obtainSolution(topicsInRange, reqTopics);
  375. }
  376.  
  377. private static int[] queryClosestQuestions(int nr, final double x, final double y) {
  378. double currRadius = INITIAL_RADIUS;
  379. Map<Question, Double> questionMap = new HashMap<Question, Double>();
  380. List<Topic> topicsInRange = null;
  381.  
  382. final Position center = new Position(x, y);
  383.  
  384. do {
  385. topicsInRange = qt.getTopicsInCircle(center, currRadius);
  386. questionMap = createQuestionMap(topicsInRange, center);
  387.  
  388. currRadius *= RADIUS_MULTIPLIER;
  389. } while (questionMap.keySet().size() < nr && topicsInRange.size() < t);
  390.  
  391.  
  392. ArrayList<Map.Entry<Question, Double>> entityTupleList = new ArrayList<Map.Entry<Question, Double>>();
  393. entityTupleList.addAll(questionMap.entrySet());
  394.  
  395. Collections.sort(entityTupleList, new Comparator<Map.Entry<Question, Double>>() {
  396. public int compare(Map.Entry<Question, Double> e1, Map.Entry<Question, Double> e2) {
  397. double dist1 = e1.getValue();
  398. double dist2 = e2.getValue();
  399.  
  400. if (Math.abs(dist1-dist2) < EPSILON){
  401. return -((Integer)e1.getKey().id).compareTo(e2.getKey().id);
  402. } else if (dist1 < dist2){
  403. return -1;
  404. } else {
  405. return 1;
  406. }
  407. }
  408. });
  409.  
  410. return obtainQuestionSolution(entityTupleList, Math.min(nr, entityTupleList.size()));
  411. }
  412.  
  413. private static int[] obtainQuestionSolution(List<Map.Entry<Question, Double>> entityTuples, int nr){
  414. int[] sol = new int[nr];
  415.  
  416. for (int i=0; i<nr; i++){
  417. sol[i] = entityTuples.get(i).getKey().id;
  418. }
  419.  
  420. return sol;
  421. }
  422.  
  423. private static Map<Question, Double> createQuestionMap(List<Topic> topicsInRange, Position center){
  424. Map<Question, Double> questionMap = new HashMap<Question, Double>();
  425.  
  426. if (topicsInRange != null){
  427. for (Topic topic:topicsInRange){
  428. if (topicMap.containsKey(topic.id)){
  429. for (Question q :topicMap.get(topic.id)){
  430. double dist = center.distanceFrom(topic.pos);
  431.  
  432. if (questionMap.containsKey(q)){
  433. if (questionMap.get(q) > dist ){
  434. questionMap.put(q, dist);
  435. }
  436. } else {
  437. questionMap.put(q, dist);
  438. }
  439. }
  440. }
  441. }
  442. }
  443.  
  444. return questionMap;
  445. }
  446.  
  447. private static int[] obtainSolution(List<? extends Entity> l, int size) {
  448. int[] sol = new int[size];
  449.  
  450. for (int i=0; i<size; i++){
  451. sol[i] = l.get(i).id;
  452. }
  453.  
  454. return sol;
  455. }
  456.  
  457. private static void initData() {
  458. topicMap = new HashMap<Integer, List<Question>>();
  459. topics = new ArrayList<Topic>();
  460. questions = new ArrayList<Question>();
  461. }
  462.  
  463. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement