Skip to content

Commit e3184a0

Browse files
authored
Merge pull request #207 from AlgorithmWithGod/khj20006
[20250306] BOJ / P3 / 미스테리 싸인 / 권혁준
2 parents ec0e659 + 02948d1 commit e3184a0

File tree

1 file changed

+197
-0
lines changed

1 file changed

+197
-0
lines changed
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
```java
2+
3+
import java.util.*;
4+
import java.io.*;
5+
6+
class Point{
7+
long x,y;
8+
Point(long x, long y){
9+
this.x = x;
10+
this.y = y;
11+
}
12+
/*
13+
* 1 : 반시계
14+
* -1 : 시계
15+
* 0 : 직선
16+
*/
17+
int ccw(Point p, Point q) {
18+
long res = p.x * q.y + q.x * this.y + this.x * p.y - (q.x * p.y + this.x * q.y + p.x * this.y);
19+
if(res > 0) return 1;
20+
if(res < 0) return -1;
21+
return 0;
22+
}
23+
}
24+
25+
class Main {
26+
27+
// IO field
28+
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
29+
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
30+
static StringTokenizer st;
31+
32+
static void nextLine() throws Exception {st = new StringTokenizer(br.readLine());}
33+
static int nextInt() {return Integer.parseInt(st.nextToken());}
34+
static long nextLong() {return Long.parseLong(st.nextToken());}
35+
static void bwEnd() throws Exception {bw.flush();bw.close();}
36+
37+
// Additional field
38+
39+
static int N, M, K;
40+
static Point[] A, B, L;
41+
static List<Point> lowerA;
42+
static List<Point> upperA;
43+
static List<Point> lowerB;
44+
static List<Point> upperB;
45+
46+
public static void main(String[] args) throws Exception {
47+
48+
ready();
49+
solve();
50+
51+
bwEnd();
52+
53+
}
54+
55+
static void ready() throws Exception{
56+
57+
nextLine();
58+
N = nextInt();
59+
M = nextInt();
60+
K = nextInt();
61+
A = new Point[N];
62+
B = new Point[M];
63+
L = new Point[K];
64+
65+
nextLine();
66+
for(int i=0;i<N;i++) A[i] = new Point(nextInt(), nextInt());
67+
68+
nextLine();
69+
for(int i=0;i<M;i++) B[i] = new Point(nextInt(), nextInt());
70+
71+
nextLine();
72+
for(int i=0;i<K;i++) L[i] = new Point(nextInt(), nextInt());
73+
74+
}
75+
76+
static void solve() throws Exception{
77+
78+
List<Point>[] resA = splitConvexHull(A);
79+
lowerA = resA[0];
80+
upperA = resA[1];
81+
82+
List<Point>[] resB = splitConvexHull(B);
83+
lowerB = resB[0];
84+
upperB = resB[1];
85+
86+
// bw.write("A's Lower Hull ===========\n");
87+
// for(Point temp:lowerA) bw.write("(" + temp.x + "," + temp.y + ") -> ");
88+
// bw.write("\n");
89+
// bw.write("A's Upper Hull ===========\n");
90+
// for(Point temp:upperA) bw.write("(" + temp.x + "," + temp.y + ") -> ");
91+
// bw.write("\n");
92+
// bw.write("B's Lower Hull ===========\n");
93+
// for(Point temp:lowerB) bw.write("(" + temp.x + "," + temp.y + ") -> ");
94+
// bw.write("\n");
95+
// bw.write("B's Upper Hull ===========\n");
96+
// for(Point temp:upperB) bw.write("(" + temp.x + "," + temp.y + ") -> ");
97+
// bw.write("\n");
98+
99+
100+
int cntA = 0, cntB = 0;
101+
for(Point now:L) {
102+
103+
boolean isInsideA = false;
104+
boolean isInsideB = false;
105+
106+
// A의 내부에 있는지
107+
long minX = lowerA.get(0).x, maxX = lowerA.get(lowerA.size()-1).x;
108+
if(minX < now.x && now.x < maxX) {
109+
isInsideA = true;
110+
int idx1 = findLowerBound(lowerA, now.x);
111+
112+
if(idx1-1 >= 0 && idx1 < lowerA.size()) isInsideA &= (now.ccw(lowerA.get(idx1-1), lowerA.get(idx1)) == 1);
113+
if(idx1 >= 0 && idx1+1 < lowerA.size()) isInsideA &= (now.ccw(lowerA.get(idx1), lowerA.get(idx1+1)) == 1);
114+
if(idx1+1 >= 0 && idx1+2 < lowerA.size()) isInsideA &= (now.ccw(lowerA.get(idx1+1), lowerA.get(idx1+2)) == 1);
115+
116+
int idx2 = findLowerBound(upperA, now.x);
117+
118+
119+
if(idx2+1 < upperA.size()) isInsideA &= (now.ccw(upperA.get(idx2+1), upperA.get(idx2)) == 1);
120+
if(idx2-1 >= 0 && idx2 < upperA.size()) isInsideA &= (now.ccw(upperA.get(idx2), upperA.get(idx2-1)) == 1);
121+
if(idx2-2 >= 0 && idx2-1 < upperA.size()) isInsideA &= (now.ccw(upperA.get(idx2-1), upperA.get(idx2-2)) == 1);
122+
123+
if(isInsideA) cntA++;
124+
}
125+
126+
// B의 내부에 있는지
127+
minX = lowerB.get(0).x;
128+
maxX = lowerB.get(lowerB.size()-1).x;
129+
if(minX < now.x && now.x < maxX) {
130+
isInsideB = true;
131+
int idx1 = findLowerBound(lowerB, now.x);
132+
133+
if(idx1 < lowerB.size() && idx1-1 >= 0) isInsideB &= (now.ccw(lowerB.get(idx1-1), lowerB.get(idx1)) == 1);
134+
if(idx1 >= 0 && idx1+1 < lowerB.size()) isInsideB &= (now.ccw(lowerB.get(idx1), lowerB.get(idx1+1)) == 1);
135+
if(idx1+2 < lowerB.size()) isInsideB &= (now.ccw(lowerB.get(idx1+1), lowerB.get(idx1+2)) == 1);
136+
137+
int idx2 = findLowerBound(upperB, now.x);
138+
139+
if(idx2+1 < upperB.size()) isInsideB &= (now.ccw(upperB.get(idx2+1), upperB.get(idx2)) == 1);
140+
if(idx2-1 >= 0 && idx2 < upperB.size()) isInsideB &= (now.ccw(upperB.get(idx2), upperB.get(idx2-1)) == 1);
141+
if(idx2-2 >= 0 && idx2-1 < upperB.size()) isInsideB &= (now.ccw(upperB.get(idx2-1), upperB.get(idx2-2)) == 1);
142+
143+
if(isInsideB) cntB++;
144+
}
145+
146+
// bw.write("(" + now.x + "," + now.y + ") is " + (isInsideA ? "inside of A\n" : "not inside of A\n"));
147+
// bw.write("(" + now.x + "," + now.y + ") is " + (isInsideB ? "inside of B\n" : "not inside of B\n"));
148+
149+
}
150+
151+
152+
int ans = K-cntA+cntB;
153+
if(ans == 0) bw.write("YES\n");
154+
else bw.write(ans + "\n");
155+
156+
}
157+
158+
static List<Point>[] splitConvexHull(Point[] P) {
159+
List<Point> lower = new ArrayList<>();
160+
List<Point> upper = new ArrayList<>();
161+
162+
long minX = (long)2e9, maxX = -(long)2e9;
163+
int idxLower = -1, idxUpper = -1;
164+
for(int i=0;i<P.length;i++) {
165+
if(P[i].x <= minX) {
166+
minX = P[i].x;
167+
idxLower = i;
168+
}
169+
if(P[i].x >= maxX) {
170+
maxX = P[i].x;
171+
idxUpper = i;
172+
}
173+
}
174+
175+
if(idxUpper < idxLower) idxUpper += P.length;
176+
for(int i=idxLower;i<=idxUpper;i++) lower.add(P[i%P.length]);
177+
for(int i=idxLower+P.length;i>=idxUpper;i--) upper.add(P[i%P.length]);
178+
179+
return new List[] {lower,upper};
180+
}
181+
182+
static int findLowerBound(List<Point> list, long x) {
183+
184+
int s = 0, e = list.size(), m = (s+e)>>1;
185+
while(s<e) {
186+
long temp = list.get(m).x;
187+
if(temp < x) s = m+1;
188+
else e = m;
189+
m = (s+e)>>1;
190+
}
191+
return m;
192+
193+
}
194+
195+
}
196+
197+
```

0 commit comments

Comments
 (0)