贪心。。。蒟蒻证明不会。。。
每一次找最大的即可,找出一次最大的,数列会分为左右两边,左边用stl优先队列维护,右边用树状数组维护。。
(线段树超时了。。。。)
代码
#include <queue> #include <cstdio> #include <iostream> #define N 100001 #define ls now << 1 #define rs now << 1 | 1 #define max(x, y) (p[x].a * 2 + p[x].b > p[y].a * 2 + p[y].b ? (x) : (y)) int n, last, now, ans, M[N]; std::priority_queue <int> q; struct node { int a, b; }p[N]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline void add(int x, int d) { for(; x; x -= x & -x) M[x] = max(M[x], d); } inline int query(int x) { int ret = 0; for(; x <= n; x += x & -x) ret = max(ret, M[x]); return ret; } int main() { int i, j, x; n = read(); for(i = 1; i <= n; i++) p[i].a = read(); for(i = 1; i <= n; i++) p[i].b = read(); for(i = 1; i <= n; i++) add(i, i); last = 0; for(i = 1; i <= n; i++) { now = query(last + 1); if(q.empty() || (q.top() < (p[now].a - p[last].a) * 2 + p[now].b)) { for(j = last + 1; j < now; j++) q.push(p[j].b); ans += (p[now].a - p[last].a) * 2 + p[now].b; last = now; } else { ans += q.top(); q.pop(); } printf("%d ", ans); } return 0; }