# [OJ#15]TR #2 画心

[OJ#15]TR #2 画心

7 -1 0 3
1 3
1 -2 3 -4 5 6 -6

9

f(i) = max{ f(j) + a(Si - Sj)2 + b(Si - Sj) + c | j ∈ [i-R, i-L]∪[0, n] }

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;

int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}

#define maxn 52510
#define maxlog 64
#define LL long long
#define LD long double

const LD oold = (LD)1.0 / 0.0;

int n, a, b, c, L, R;

struct Vec {
LD x, y; int id;
Vec() {}
Vec(LD _1, LD _2, int _3): x(_1), y(_2), id(_3) {}
Vec operator - (const Vec& t) const { return Vec(x - t.x, y - t.y, id); }
LD operator ^ (const Vec& t) const { return x * t.y - y * t.x; }
bool operator < (const Vec& t) const { return x < t.x; }
} ps[maxn];

void target(int o, int l, int r, int ql, int qr, int id) {
if(ql <= l && r <= qr) need[++ToT] = id, nxt[ToT] = head[o], head[o] = ToT;
else {
int mid = l + r >> 1, lc = o << 1, rc = lc | 1;
if(ql <= mid) target(lc, l, mid, ql, qr, id);
if(qr > mid) target(rc, mid + 1, r, ql, qr, id);
}
return ;
}
LD val[maxn<<2], f[maxn], S[maxn];
int q[maxn], top;
vector <int> poly[maxn<<2];
LD calc(int j, int i) { // f[j] -> f[i], return f[i]
return (LD)f[j] + (LD)a * (S[i] - S[j]) * (S[i] - S[j]) + (LD)b * (S[i] - S[j]) + c;
}
void solve(int o, int l, int r) {
int mid = l + r >> 1, lc = o << 1, rc = lc | 1, cp = 0;
for(int e = head[o]; e; e = nxt[e]) {
int j = need[e];
//		printf("in vetex %d: %d\n", o, j);
ps[++cp] = Vec(S[j], f[j] + (LD)a * S[j] * S[j] - (LD)b * S[j], j);
}
if(cp) {
sort(ps + 1, ps + cp + 1);
q[top = 1] = 1;
while(q[1] <= cp && ps[q[1]].y == -oold) q[1]++;
for(int i = q[1] + 1; i <= cp; i++) {
if(ps[i].y == -oold) continue;
while(top > 1 && (ps[q[top]] - ps[q[top-1]] ^ ps[i] - ps[q[top]]) >= 0) top--;
q[++top] = i;
}
if(q[1] > cp) top = 0;
while(top && ps[q[top]].y == -oold) top--;
if(top) for(int i = 1; i <= top; i++) poly[o].push_back(ps[q[i]].id);
}
if(l == r) {
int u = o;
while(u) {
int _l = 0, _r = poly[u].size() - 1;
while(_l < _r) {
int _mid = _l + _r >> 1;
if(_mid < poly[u].size() - 1 && calc(poly[u][_mid], l) <= calc(poly[u][_mid+1], l))
_l = _mid + 1;
else _r = _mid;
}
if(poly[u].size()) f[l] = max(f[l], calc(poly[u][_l], l)); // , printf("u: %d\n", u);
u >>= 1;
}
//		printf("f[%d] = %.0Lf\n", l, f[l]);
}
else solve(lc, l, mid), solve(rc, mid + 1, r);
return ;
}

int main() {
for(int i = 1; i <= n; i++) S[i] = S[i-1] + read();

for(int i = 1; i <= n; i++) f[i] = -oold;
for(int i = 0; i <= n; i++) target(1, 0, n, i + L, min(i + R, n), i);
solve(1, 0, n);

printf("%.0Lf\n", f[n]);

return 0;
}


posted @ 2017-09-19 20:53  xjr01  阅读(175)  评论(0编辑  收藏  举报