偶然看到Petr的AC代码,真的惊呆了,终于知道自己弱在哪里了,终于找到喜欢的风格了。
1 import java.util.List; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.util.Arrays; 5 import java.util.ArrayList; 6 import java.io.BufferedReader; 7 import java.util.Comparator; 8 import java.io.OutputStream; 9 import java.io.PrintWriter; 10 import java.util.Random; 11 import java.util.StringTokenizer; 12 import java.util.Collections; 13 import java.io.InputStream; 14 15 /** 16 * Built using CHelper plug-in 17 * Actual solution is at the top 18 */ 19 public class Main { 20 public static void main(String[] args) { 21 InputStream inputStream = System.in; 22 OutputStream outputStream = System.out; 23 InputReader in = new InputReader(inputStream); 24 PrintWriter out = new PrintWriter(outputStream); 25 TaskE solver = new TaskE(); 26 solver.solve(1, in, out); 27 out.close(); 28 } 29 } 30 31 class TaskE { 32 static class Obstacle { 33 int x; 34 int y; 35 } 36 37 static class SumThenDiffComparator implements Comparator<Obstacle> { 38 static final SumThenDiffComparator INSTANCE = new SumThenDiffComparator(); 39 40 public int compare(Obstacle o1, Obstacle o2) { 41 int s1 = o1.x + o1.y; 42 int s2 = o2.x + o2.y; 43 if (s1 != s2) 44 return s1 - s2; 45 s1 = o1.x - o1.y; 46 s2 = o2.x - o2.y; 47 return s1 - s2; 48 } 49 } 50 51 static class DiffThenSumComparator implements Comparator<Obstacle> { 52 static final DiffThenSumComparator INSTANCE = new DiffThenSumComparator(); 53 54 public int compare(Obstacle o1, Obstacle o2) { 55 int s1 = o1.x - o1.y; 56 int s2 = o2.x - o2.y; 57 if (s1 != s2) 58 return s1 - s2; 59 s1 = o1.x + o1.y; 60 s2 = o2.x + o2.y; 61 return s1 - s2; 62 } 63 } 64 65 static class Obstacles { 66 Obstacle[] bySum; 67 Obstacle[] byDiff; 68 int maxx; 69 int maxy; 70 71 public Obstacles(Obstacle[] ob, int maxx, int maxy) { 72 this.maxx = maxx; 73 this.maxy = maxy; 74 bySum = ob.clone(); 75 Arrays.sort(bySum, SumThenDiffComparator.INSTANCE); 76 byDiff = ob.clone(); 77 Arrays.sort(byDiff, DiffThenSumComparator.INSTANCE); 78 } 79 80 public boolean haveObstacle(int x, int y) { 81 if (x <= 0 || x > maxx || y <= 0 || y > maxy) return true; 82 Obstacle cur = new Obstacle(); 83 cur.x = x; 84 cur.y = y; 85 return Arrays.binarySearch(bySum, cur, SumThenDiffComparator.INSTANCE) >= 0; 86 } 87 88 public Obstacle getNext(int x, int y, int dx, int dy) { 89 Obstacle cur = new Obstacle(); 90 cur.x = x; 91 cur.y = y; 92 if (dx == dy) { 93 int pos = Arrays.binarySearch(byDiff, cur, DiffThenSumComparator.INSTANCE); 94 if (pos >= 0) throw new RuntimeException(); 95 pos = -(pos + 1); 96 if (dx > 0) { 97 if (pos < byDiff.length && x - y == byDiff[pos].x - byDiff[pos].y) 98 return byDiff[pos]; 99 else 100 return getBoundary(x, y, dx, dy); 101 } else { 102 --pos; 103 if (pos >= 0 && x - y == byDiff[pos].x - byDiff[pos].y) 104 return byDiff[pos]; 105 else 106 return getBoundary(x, y, dx, dy); 107 } 108 } else { 109 int pos = Arrays.binarySearch(bySum, cur, SumThenDiffComparator.INSTANCE); 110 if (pos >= 0) { 111 throw new RuntimeException(); 112 } 113 pos = -(pos + 1); 114 if (dx > 0) { 115 if (pos < bySum.length && x + y == bySum[pos].x + bySum[pos].y) 116 return bySum[pos]; 117 else 118 return getBoundary(x, y, dx, dy); 119 } else { 120 --pos; 121 if (pos >= 0 && x + y == bySum[pos].x + bySum[pos].y) 122 return bySum[pos]; 123 else 124 return getBoundary(x, y, dx, dy); 125 } 126 } 127 } 128 129 private Obstacle getBoundary(int x, int y, int dx, int dy) { 130 int times = Integer.MAX_VALUE; 131 if (dx > 0) times = Math.min(times, maxx + 1 - x); else times = Math.min(times, x); 132 if (dy > 0) times = Math.min(times, maxy + 1 - y); else times = Math.min(times, y); 133 Obstacle res = new Obstacle(); 134 res.x = x + times * dx; 135 res.y = y + times * dy; 136 return res; 137 } 138 } 139 140 Obstacles obstacles; 141 int xs; 142 int ys; 143 int dx; 144 int dy; 145 List<Segment> segments = new ArrayList<Segment>(); 146 147 static class Segment implements Comparable<Segment> { 148 int x1; 149 int y1; 150 int x2; 151 int y2; 152 153 Segment(int x1, int y1, int x2, int y2) { 154 if (x1 < x2) { 155 this.x1 = x1; 156 this.y1 = y1; 157 this.x2 = x2; 158 this.y2 = y2; 159 } else { 160 this.x1 = x2; 161 this.y1 = y2; 162 this.x2 = x1; 163 this.y2 = y1; 164 } 165 } 166 167 public int compareTo(Segment o) { 168 if (x1 != o.x1) return x1 - o.x1; 169 if (y1 != o.y1) return y1 - o.y1; 170 if (x2 != o.x2) return x2 - o.x2; 171 return y2 - o.y2; 172 } 173 } 174 175 public void solve(int testNumber, InputReader in, PrintWriter out) { 176 int maxx = in.nextInt(); 177 int maxy = in.nextInt(); 178 int k = in.nextInt(); 179 Obstacle[] ob = new Obstacle[k]; 180 for (int i = 0; i < k; ++i) { 181 ob[i] = new Obstacle(); 182 ob[i].x = in.nextInt(); 183 ob[i].y = in.nextInt(); 184 } 185 xs = in.nextInt(); 186 ys = in.nextInt(); 187 String dir = in.next(); 188 if (dir.equals("NE")) { 189 dx = -1; 190 dy = 1; 191 } else if (dir.equals("NW")) { 192 dx = -1; 193 dy = -1; 194 } else if (dir.equals("SE")) { 195 dx = 1; 196 dy = 1; 197 } else if (dir.equals("SW")) { 198 dx = 1; 199 dy = -1; 200 } else throw new RuntimeException(); 201 long res = doit(maxx, maxy, ob); 202 out.println(res); 203 } 204 205 private long doit(int maxx, int maxy, Obstacle[] ob) { 206 shuffle(ob); 207 obstacles = new Obstacles(ob, maxx, maxy); 208 oneStep(); 209 int exs = xs; 210 int eys = ys; 211 int edx = dx; 212 int edy = dy; 213 segments.clear(); 214 do { 215 oneStep(); 216 } while (xs != exs || ys != eys || dx != edx || dy != edy); 217 List<Segment> plus = new ArrayList<Segment>(); 218 List<Segment> minus = new ArrayList<Segment>(); 219 for (Segment s : segments) { 220 if (s.x1 + s.y1 == s.x2 + s.y2) { 221 plus.add(s); 222 } else { 223 minus.add(s); 224 } 225 } 226 Collections.sort(plus); 227 Collections.sort(minus); 228 int cnt = 0; 229 for (int i = 0; i < plus.size(); ++i) { 230 if (i == 0 || plus.get(i).compareTo(plus.get(i - 1)) > 0) 231 plus.set(cnt++, plus.get(i)); 232 } 233 while (plus.size() > cnt) plus.remove(plus.size() - 1); 234 cnt = 0; 235 for (int i = 0; i < minus.size(); ++i) { 236 if (i == 0 || minus.get(i).compareTo(minus.get(i - 1)) > 0) 237 minus.set(cnt++, minus.get(i)); 238 } 239 while (minus.size() > cnt) minus.remove(minus.size() - 1); 240 long res = 0; 241 for (Segment x : plus) { 242 res += Math.abs(x.x1 - x.x2) + 1; 243 } 244 for (Segment x : minus) { 245 res += Math.abs(x.x1 - x.x2) + 1; 246 } 247 return res; 248 } 249 250 private void oneStep() { 251 Obstacle meet = obstacles.getNext(xs, ys, dx, dy); 252 int px = meet.x - dx; 253 int py = meet.y - dy; 254 segments.add(new Segment(xs, ys, px, py)); 255 boolean haveX = obstacles.haveObstacle(px, meet.y); 256 boolean haveY = obstacles.haveObstacle(meet.x, py); 257 if (haveX && !haveY) { 258 xs = meet.x; 259 ys = py; 260 dy = -dy; 261 } else if (haveY && !haveX) { 262 xs = px; 263 ys = meet.y; 264 dx = -dx; 265 } else { 266 xs = px; 267 ys = py; 268 dx = -dx; 269 dy = -dy; 270 } 271 } 272 273 Random random = new Random(System.currentTimeMillis() + 438467315); 274 275 private void shuffle(Obstacle[] x) { 276 for (int i = 0; i < x.length; ++i) { 277 int j = i + random.nextInt(x.length - i); 278 Obstacle tmp = x[i]; 279 x[i] = x[j]; 280 x[j] = tmp; 281 } 282 } 283 } 284 285 class InputReader { 286 public BufferedReader reader; 287 public StringTokenizer tokenizer; 288 289 public InputReader(InputStream stream) { 290 reader = new BufferedReader(new InputStreamReader(stream)); 291 tokenizer = null; 292 } 293 294 public String next() { 295 while (tokenizer == null || !tokenizer.hasMoreTokens()) { 296 try { 297 tokenizer = new StringTokenizer(reader.readLine()); 298 } catch (IOException e) { 299 throw new RuntimeException(e); 300 } 301 } 302 return tokenizer.nextToken(); 303 } 304 305 public int nextInt() { 306 return Integer.parseInt(next()); 307 } 308 309 }