一張手寫的題解html
這些點必定在凸殼上c++
證實能夠參照gxz大佬的題解git
這個題的作法是按照詢問做爲時間軸,把每一個插入的向量視爲在一個時間區間 $[l,r]$ 內有效,在 $[l,r]$ 在線段樹上對應的 $O(log n)$ 個區間上打上標記,而後dfs一下整棵線段樹,對於每一個dfs到的線段樹節點,遍歷這個節點有的標記,維護出凸殼,而後在凸殼上二分斜率(也能夠三分~),更新這個節點對應區間的詢問的答案(這樣不須要進行刪除操做)數組
對着std調了很久...atom
每次二分是 $O(logn)$ 每一個節點被插入了 $O(logn)$ 次,總共插入了 $O(nlogn)$次,因此複雜度是 $O(nlog^2n)$spa
好像有個什麼性質能夠少個log,但這份代碼竟然跑進了前兩頁,因此彷佛不必了,實際上是不想再寫了code
#include <bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 7; typedef long long ll; typedef long double lf; const lf eps = 1e-8; template<class A, class B> inline void chmax(A &a, B b) { if (a < b) a = b; } inline int read() { register int c = getchar(), x = 0; while (!isdigit(c)) c = getchar(); while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); return x; } struct Vec { int x, y; Vec(int x, int y) : x(x), y(y) {} Vec() {} inline Vec operator +(const Vec&b) const {return Vec(x + b.x, y + b.y);} inline Vec operator -(const Vec&b) const {return Vec(x - b.x, y - b.y);} inline ll operator *(const Vec&a) const {return x * 1ll * a.x + y * 1ll * a.y;} inline ll operator %(const Vec&a) const {return x * 1ll * a.y - y * 1ll * a.x;} } q[MAXN]; struct atom { Vec a, b;//b是有效時間 } a[MAXN]; int n, op, x, y, sta[MAXN], top, tot, tot1; //由於棧存的是編號,因此數組嵌套有點多,能夠存vec減小嵌套 ll ans[MAXN]; vector<int> t[530000]; inline bool cmp(int x, int y) { if (a[x].a.x != a[y].a.x) return a[x].a.x < a[y].a.x;//按照x,y排序 求出凸殼 return a[x].a.y < a[y].a.y; } inline void add(int o, int l, int r, int ql, int qr, int v) { if (ql > qr) return ; if (ql <= l && r <= qr) return void(t[o].push_back(v)); int mid = l + r >> 1; if (ql <= mid) add(o << 1, l, mid, ql, qr, v); if (qr > mid) add(o << 1 | 1, mid + 1, r, ql, qr, v); } inline lf slope(const Vec &a, const Vec &b) { if (fabs(a.x - b.x) < eps) return 1e9; return lf(a.y - b.y) / (a.x - b.x); } inline ll query(int o, int pos) { //二分q[pos]垂線的斜率處於凸包的哪一個位置 lf K = -1.0 * q[pos].x / q[pos].y; //-1.0 / (q[pos].y / q[pos].x); if (top == 1 || K > slope(a[t[o][sta[1]]].a, a[t[o][sta[2]]].a) + eps) return q[pos] * a[t[o][sta[1]]].a; if (K + eps < slope(a[t[o][sta[top - 1]]].a, a[t[o][sta[top]]].a)) return q[pos] * a[t[o][sta[top]]].a;//判邊界,不知道哪些不須要...但判了總沒壞處 int l = 2, r = top, ans = 1; while (l <= r) { int mid = l + r >> 1; if (K < slope(a[t[o][sta[mid - 1]]].a, a[t[o][sta[mid]]].a) + eps) ans = mid, l = mid + 1; else r = mid - 1; } return q[pos] * a[t[o][sta[ans]]].a; } inline void solve(int o, int l, int r) { if (!t[o].size()) return ; sort(t[o].begin(), t[o].end(), cmp); top = 0; for (int i = 0; i < t[o].size(); ++i) { while (top > 1 && (a[t[o][i]].a - a[t[o][sta[top - 1]]].a) % (a[t[o][sta[top]]].a - a[t[o][sta[top - 1]]].a) <= 0) --top;//維護凸殼 sta[++top] = i; } for (int i = l; i <= r; ++i) chmax(ans[i], query(o, i)); } inline void dfs(int o, int l, int r) { solve(o, l, r); if (l == r) return ; int mid = l + r >> 1; dfs(o << 1, l, mid), dfs(o << 1 | 1, mid + 1, r); } int main() { int m = read(); while (m--) { op = read(), x = read(); if (op != 2) { y = read(); if (op == 1) a[++tot1] = (atom) {Vec(x, y), Vec(tot + 1, -1)}; else q[++tot] = Vec(x, y); } else a[x].b.y = tot; } for (int i = 1; i <= tot1; ++i) add(1, 1, tot, a[i].b.x, a[i].b.y == -1 ? tot : a[i].b.y, i); dfs(1, 1, tot); for (int i = 1; i <= tot; ++i) printf("%lld\n", ans[i]); return 0; }