제출 #748543

#제출 시각아이디문제언어결과실행 시간메모리
748543alex_2008송신탑 (IOI22_towers)C++17
17 / 100
1375 ms186040 KiB
#include "towers.h" #include <iostream> #include <vector> #include <cmath> #include <set> #include <algorithm> using namespace std; int ind = -1; bool ch = true; vector <int> h; const int N = 100100, M = 20; int mx[N][M], Left[N], Right[N], pref[N], LS[N], RS[N]; int mxleft[N][M], mnright[N][M]; struct Node { int val; int left; int right; Node* ls; Node* rs; }; Node* roots[N]; int tree[4 * N], maxim[4 * N], minim[4 * N]; int minnumber = 2e9, answer_for_another_tree = 0; void build_another_tree(int v, int tl, int tr) { if (tl == tr) { maxim[v] = h[tl]; minim[v] = h[tl]; tree[v] = 0; } else { int tm = (tl + tr) / 2; build_another_tree(2 * v, tl, tm); build_another_tree(2 * v + 1, tm + 1, tr); maxim[v] = max({ maxim[2 * v], maxim[2 * v + 1] }); minim[v] = min({ minim[2 * v], minim[2 * v + 1] }); tree[v] = max({ tree[2 * v], tree[2 * v + 1], maxim[2 * v + 1] - minim[2 * v] }); } } void query_in_another_tree(int v, int tl, int tr, int l, int r) { if (tr < l || tl > r) return; if (tl >= l && tr <= r) { answer_for_another_tree = max(answer_for_another_tree, tree[v]); answer_for_another_tree = max(answer_for_another_tree, maxim[v] - minnumber); minnumber = min(minnumber, minim[v]); return; } int tm = (tl + tr) / 2; query_in_another_tree(2 * v, tl, tm, l, r); query_in_another_tree(2 * v + 1, tm + 1, tr, l, r); } void build_tree(Node* v) { if (v->left == v->right) { v->val = 1; return; } else { int tm = (v->left + v->right) / 2; Node* ls = new Node{ 0, v->left, tm, nullptr, nullptr }; Node* rs = new Node{ 0, tm + 1, v->right, nullptr, nullptr }; build_tree(ls); build_tree(rs); v->ls = ls; v->rs = rs; v->val = ls->val + rs->val; } } void update(Node* old, Node* neww, int pos) { *neww = *old; if (neww->left > pos || neww->right < pos) return; if (neww->left == neww->right) { neww->val = 0; return; } int tm = (neww->left + neww->right) / 2; Node* ls = new Node{ 0, neww->left, tm, nullptr, nullptr }; Node* rs = new Node{ 0, tm + 1, neww->right, nullptr, nullptr }; update(old->ls, ls, pos); update(old->rs, rs, pos); neww->ls = ls; neww->rs = rs; neww->val = ls->val + rs->val; } int ql = 2e9, qr = -1; void query1(Node* v, int l) { if (v->val == 0) return; if (v->right < l) return; if (v->left >= l) { while (v->left != v->right) { if (v->ls->val > 0) { v = v->ls; } else { v = v->rs; } } ql = min(ql, v->left); return; } query1(v->ls, l); query1(v->rs, l); } void query2(Node* v, int r) { if (v->val == 0) return; if (v->left > r) return; if (v->right <= r) { while (v->left != v->right) { if (v->rs->val > 0) { v = v->rs; } else v = v->ls; } qr = max(qr, v->left); return; } query2(v->ls, r); query2(v->rs, r); } int query3(Node* v, int l, int r) { if (v->left > r || v->right < l) return 0; if (v->left >= l && v->right <= r) return v->val; return query3(v->ls, l, r) + query3(v->rs, l, r); } vector <pair<int, int>> esim; vector <int> indexes; bool check = true; int findmaxinrange(int L, int R) { if (L > R) return 0; int u = log2(R - L + 1); return max(mx[L][u], mx[R - (1 << u) + 1][u]); } int findmininrange(int L, int R) { return 1; } int findmininrange(int L, int R, int w) { if (L > R) return 2e9 + 1; int u = log2(R - L + 1); if (w == 1) return max(mxleft[L][u], mxleft[R - (1 << u) + 1][u]); return min(mnright[L][u], mnright[R - (1 << u) + 1][u]); } void init(int n, vector<int> a) { ch = true; ind = -1; h = a; pref[0] = 0; for (int i = 0; i < n - 1; ++i) { if (a[i] > a[i + 1]) { if (ind == -1) ind = i; } else { if (ind != -1) ch = false; } } LS[0] = -1; RS[n - 1] = -1; for (int i = 1; i < n; i++) { int v = i - 1; while (v != -1 && a[i] < a[v]) { v = LS[v]; } LS[i] = v; } for (int i = n - 2; i >= 0; i--) { int v = i + 1; while (v != -1 && a[i] < a[v]) { v = RS[v]; } RS[i] = v; } for (int i = 1; i < n - 1; i++) { pref[i] = pref[i - 1]; if (a[i] < a[i + 1] && a[i] < a[i - 1]) pref[i]++; } for (int i = 0; i < n; i++) { mx[i][0] = a[i]; } for (int j = 1; j < 20; j++) { for (int i = n - 1; i >= 0; i--) { mx[i][j] = max(mx[i][j - 1], mx[min(n - 1, i + (1 << (j - 1)))][j - 1]); } } for (int i = 0; i < n; i++) { int hmn = 2e9; if (LS[i] != -1) { hmn = min(hmn, findmaxinrange(LS[i] + 1, i - 1)); } if (RS[i] != -1) { hmn = min(hmn, findmaxinrange(i + 1, RS[i] - 1)); } int u = hmn - a[i]; esim.push_back({ u, i }); } sort(esim.begin(), esim.end()); roots[0] = new Node{0, 0, n - 1, nullptr, nullptr}; build_tree(roots[0]); for (int i = 1; i < n; i++) { roots[i] = new Node{ 0, 0, n - 1, nullptr, nullptr }; update(roots[i - 1], roots[i], esim[i - 1].second); } build_another_tree(1, 0, n - 1); } int querynumber = 0; int max_towers(int L, int R, int D) { int n = (int)h.size(); int left = 0, right = n - 1, answ = -1; while (left <= right) { int mid = (left + right) / 2; if (esim[mid].first >= D) { answ = mid; right = mid - 1; } else left = mid + 1; } if (answ == -1) return 1; int ans = query3(roots[answ], L, R); ql = 2e9; qr = -1; query1(roots[answ], L); query2(roots[answ], R); minnumber = 2e9; answer_for_another_tree = 0; if (ql != 2e9) { int left = 0, right = ql - 1, r__ = -1; while (left <= right) { int mid = (left + right) / 2; if (findmaxinrange(mid, ql) - h[L] >= D) { r__ = mid; left = mid + 1; } else right = mid - 1; } if (r__ != -1 && r__ >= L) { query_in_another_tree(1, 0, n - 1, L, r__); if (answer_for_another_tree >= D) ++ans; } } minnumber = 2e9; answer_for_another_tree = 0; if (qr != -1) { int left = qr + 1, right = n - 1, r__ = -1; while (left <= right) { int mid = (left + right) / 2; if (findmaxinrange(qr, mid) - h[R] >= D) { r__ = mid; right = mid - 1; } else left = mid + 1; } if (r__ != -1 && r__ <= R) { query_in_another_tree(1, 0, n - 1, r__, R); if (answer_for_another_tree >= D) ++ans; } } if (ans == 0) ++ans; return ans; //query left = INF, query right = -1 /* 7 1 10 20 60 40 50 30 70 1 5 10 */ /*auto it = lower_bound(indexes.begin(), indexes.end(), L); int ans = upper_bound(indexes.begin(), indexes.end(), R) - lower_bound(indexes.begin(), indexes.end(), L); if (it != indexes.end()) { int q = Left[*it]; if (L < q) { if (findmininrange(L, q - 1, 2) < *it) { ++ans; } } } it = upper_bound(indexes.begin(), indexes.end(), R); if (it != indexes.begin()) { --it; int q = Right[*it]; if (q < R) { if (findmininrange(q + 1, R, 1) > *it) { ++ans; } } } if (ans == 0) ++ans;*/ return ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...