首先对于一个给定的图形,要找到是否存在答案非常简单。。。
只要维护当然图形的凸包,看一下是否有线段在这条直线上方,直接二分即可,单次询问的时间复杂度$O(logn)$
现在用线段树维护凸包,即对于一个区间$[l, r]$,我们维护点$[P_l, P_{r +1}]$形成的凸包
于是每次查询只要在线段树上二分,总复杂度$O(nlogn + nlog^2n)$(建树 + 查询)
1 /************************************************************** 2 Problem: 4049 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:5052 ms 7 Memory:73960 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <vector> 12 13 using namespace std; 14 typedef long long ll; 15 const int N = 1e5 + 5; 16 17 int read(); 18 19 int n; 20 21 struct point { 22 int x, y; 23 point(int _x, int _y) : x(_x), y(_y) {} 24 point() {} 25 26 inline point operator + (const point &p) const { 27 return point(x + p.x, y + p.y); 28 } 29 inline point operator - (const point &p) const { 30 return point(x - p.x, y - p.y); 31 } 32 inline ll operator * (const point &p) const { 33 return 1ll * x * p.y - 1ll * y * p.x; 34 } 35 36 inline void get() { 37 x = read(), y = read(); 38 } 39 40 friend inline ll calc(const point &a, const point &b, const point &c) { 41 return (a - b) * (c - b); 42 } 43 } p[N]; 44 45 struct convex { 46 vector <point> s; 47 48 inline void clear() { 49 s.clear(); 50 } 51 #define top ((int) s.size() - 1) 52 inline void insert(const point &p) { 53 while (top > 0 && calc(p, s[top - 1], s[top]) <= 0) s.pop_back(); 54 s.push_back(p); 55 } 56 57 #define mid (l + r >> 1) 58 inline bool query(const point &p, const point &q) { 59 int l = 0, r = top - 1; 60 while (l < r) { 61 if (calc(s[mid], p, q) < calc(s[mid + 1], p, q)) r = mid; 62 else l = mid + 1; 63 } 64 return calc(s[l], p, q) < 0 || calc(s[l + 1], p, q) < 0; 65 } 66 #undef mid 67 #undef top 68 }; 69 70 struct seg { 71 seg *ls, *rs; 72 convex c; 73 74 #define Len (1 << 16) 75 inline void* operator new(size_t, int f = 0) { 76 static seg mempool[N << 2], *c; 77 if (f) c = mempool; 78 c -> ls = c -> rs = NULL, c -> c.clear(); 79 return c++; 80 } 81 #undef Len 82 83 #define mid (l + r >> 1) 84 void build(int l, int r) { 85 int i; 86 for (i = l; i <= r + 1; ++i) c.insert(p[i]); 87 if (l == r) return; 88 (ls = new()seg) -> build(l, mid); 89 (rs = new()seg) -> build(mid + 1, r); 90 } 91 92 int query(int l, int r, int L, int R, const point &p, const point &q) { 93 if (R < l || r < L) return 0; 94 if (L <= l && r <= R) { 95 if (!c.query(p, q)) return 0; 96 if (l == r) return l; 97 } 98 int res = ls -> query(l, mid, L, R, p, q); 99 return res ? res : rs -> query(mid + 1, r, L, R, p, q); 100 } 101 #undef mid 102 } *T; 103 104 int main() { 105 int Tmp, i; 106 for (Tmp = read(); Tmp; --Tmp) { 107 n = read(); 108 for (i = 1; i <= n; ++i) p[i].get(); 109 (T = new(1)seg) -> build(1, n - 1); 110 for (i = 1; i < n - 1; ++i) 111 printf("%d ", T -> query(1, n - 1, i + 1, n - 1, p[i], p[i + 1])); 112 puts("0"); 113 } 114 return 0; 115 } 116 117 inline int read() { 118 static int x; 119 static char ch; 120 x = 0, ch = getchar(); 121 while (ch < ‘0‘ || ‘9‘ < ch) 122 ch = getchar(); 123 while (‘0‘ <= ch && ch <= ‘9‘) { 124 x = x * 10 + ch - ‘0‘; 125 ch = getchar(); 126 } 127 return x; 128 }
时间: 2024-10-01 06:56:40