首先对于一个给定的图形,要找到是否存在答案非常简单。。。

只要维护当然图形的凸包,看一下是否有线段在这条直线上方,直接二分即可,单次询问的时间复杂度$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 }
View Code

 

posted on 2015-05-25 21:00  Xs酱~  阅读(653)  评论(0编辑  收藏  举报