【CodeVS 1199】【NOIP 2012】开车旅行
http://codevs.cn/problem/1199/
主要思想是倍增,对于第一个回答从后往前扫,依次插入平衡树中。
我写的splay,比较繁琐。
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N = 100003; int in() { int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = (k << 3) + (k << 1) + c - '0'; return k * fh; } int h[N], n, m, nxt_a[N], nxt_b[N], f[N][18], sum_a[N][18], sum_b[N][18]; struct Splay { struct node { node *ch[2], *fa; int id, num; bool pl() {return fa->ch[1] == this;} void setc(node *r, bool c) {ch[c] = r; r->fa = this;} } *root, *null; void init() { null = new node; null->id = null->num = 0; null->ch[0] = null->ch[1] = null->fa = null; root = null; } void printall(node *r) { if (r == null) return; printall(r->ch[0]); printf("%d ", r->num); printall(r->ch[1]); } void rotate(node *r) { node *f = r->fa; bool c = r->pl(); if (f != root) f->fa->setc(r, f->pl()); else root = r, r->fa = null; f->setc(r->ch[!c], c); r->setc(f, !c); } void splay(node *r) { for(; r->fa != null; rotate(r)) if (r->fa->fa != null) rotate(r->fa->pl() == r->pl() ? r->fa : r); } struct data { int del, h, id; bool operator < (const data &A) const { return (del == A.del ? h < A.h : del < A.del); } } a[5]; node *getl(int num, int to) { node *r = root->ch[0]; if (r == null) {a[to] = (data) {0x7fffffff, 0, 0}; return r;} while (r->ch[1] != null) r = r->ch[1]; a[to] = (data) {abs(num - r->num), r->num, r->id}; return r; } node *getr(int num, int to) { node *r = root->ch[1]; if (r == null) {a[to] = (data) {0x7fffffff, 0, 0}; return r;} while (r->ch[0] != null) r = r->ch[0]; a[to] = (data) {abs(num - r->num), r->num, r->id}; return r; } void mk_nxt(int &back_1, int &back_2, int id, int num) { node *r = root; if (r == null) { root = new node; root->id = id; root->num = num; root->ch[0] = root->ch[1] = root->fa = null; back_1 = back_2 = 0; return; } bool c; while (true) { if (r->num > num) c = 0; else c = 1; if (r->ch[c] == null) { r->ch[c] = new node; r->ch[c]->fa = r; r = r->ch[c]; r->id = id; r->num = num; r->ch[0] = r->ch[1] = null; splay(r); node *ll = getl(num, 0), *rr = getr(num, 1); if (ll != null) {splay(ll); getl(num, 2);} else a[2] = (data) {0x7fffffff, 0, 0}; if (rr != null) {splay(rr); getr(num, 3);} else a[3] = (data) {0x7fffffff, 0, 0}; sort(a, a + 4); if (a[1].id != 0) { back_1 = a[1].id; back_2 = a[0].id; } else if (a[0].id != 0) { back_1 = 0; back_2 = a[0].id; } else { back_1 = 0; back_2 = 0; } return; } else r = r->ch[c]; } } } T; void cal(int &a, int &b, int s, int x) { a = b = 0; for(int i = 17; i >= 0; --i) if (f[s][i] && sum_a[s][i] + sum_b[s][i] <= x) { a += sum_a[s][i]; b += sum_b[s][i]; x -= sum_a[s][i]; x -= sum_b[s][i]; s = f[s][i]; } if (sum_a[s][0] <= x && nxt_a[s]) a += sum_a[s][0]; } int main() { T.init(); n = in(); for(int i = 1; i <= n; ++i) h[i] = in(); for(int i = n; i >= 1; --i) T.mk_nxt(nxt_a[i], nxt_b[i], i, h[i]); for(int i = 1; i <= n; ++i) { if (nxt_a[i]) sum_a[i][0] = abs(h[nxt_a[i]] - h[i]); if (nxt_b[nxt_a[i]]) { sum_b[i][0] = abs(h[nxt_b[nxt_a[i]]] - h[nxt_a[i]]); f[i][0] = nxt_b[nxt_a[i]]; } } for(int j = 1; j <= 17; ++j) for(int i = 1; i <= n; ++i) if (f[f[i][j - 1]][j - 1]) { f[i][j] = f[f[i][j - 1]][j - 1]; sum_a[i][j] = sum_a[i][j - 1] + sum_a[f[i][j - 1]][j - 1]; sum_b[i][j] = sum_b[i][j - 1] + sum_b[f[i][j - 1]][j - 1]; } int a, b, s, x, ans = 0; double ans_num = -1.0, now; x = in(); for(int i = 1; i <= n; ++i) { cal(a, b, i, x); if (b != 0) now = 1.0 * a / b; else now = -1.0; if (ans_num == -1.0 || (ans_num != -1.0 && now != -1.0 && now <= ans_num)) if (fabs(ans_num - now) < 1e-12) { if (h[i] > h[ans]) ans = i; } else ans_num = now, ans = i; } printf("%d\n", ans); m = in(); int i = 0; while (m--) { ++i; s = in(); x = in(); cal(a, b, s, x); printf("%d %d\n", a, b); } return 0; }
_(:з」∠)_
NOI 2017 Bless All