[OJ#15]TR #2 画心

试题描述

渠是一名画师。渠有一支神奇的画笔,可以画尽因果。

渠要画一幅画,这幅画由N个线段组成,线段从1开始编号,第i条线段有一个特殊的因果值Ai

由于画太长了,渠不可能一次画完,于是渠打算将这N条线段分成若干组来画,每一组的长度要求在[L,R]之间,且必须是编号连续的一段。

对于因果值之和为x的一组线段,渠画完后种下的因果为ax2+bx+c。渠想知道渠将这N条线段画完,最多收获多少因果呢?

输入

输入共三行。

第一行为4个整数N,a,b,c,表示线段的数目与给定的参数。

第二行为2个正整数L,R,为每组长度限制的区间。

第三行为N个整数Ai,分别表示每一条线段的因果值。

输出

仅一行,为最多收获的因果数,保证答案在long long范围之内。

输入示例

 -  

 -  -   -

输出示例


数据规模及约定

对于20%的数据 : 1≤N≤10。

对于40%的数据 : 1≤N≤103

另有20%的数据 : L=1, R=N, 0≤Ai≤105

另有20%的数据 : L=1, R=N。

对于100%的数据 : 1≤N≤52501, 0≤b,c≤52501, 0≤|Ai|≤105, −10<a<0。

题解

新学一个叫线段树分治。

首先设 f(i) 表示前 i 条线段能获得的最大分数(由于“因果值”太奇怪,改称分数),那么直接可以得出转移方程(设数列 A 的前缀和为数列 S)

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

这题推推式子发现是斜率优化题,但是由于 A 中元素有正有负,顾数列 S 无单调性,并且会发现斜率也没有单调性,所以不能简单处理了。

这时候我们考虑一个点能转移到哪,显然也是一个区间(即 f(j) 可以转移到 [j+L, j+R] 这个区间),于是我们可以在线段树上 [j+L, j+R] 所对应的 log(n) 个区间加上 j 的标记;那么对于线段树某个节点,它上面所有标记都适用于它子树中所有的节点(即这个节点上的标记可以转移到所有子节点所对应的位置)。

然后我们就可以按 DFS 序遍历这棵线段树;考虑遍历到某个节点时,该节点上的标记一定在该节点所表示区间的左边,由于我们是按照 DFS 序处理的,所以该节点上的标记一定都已经得出了答案,所以就可以直接用这些标记离线维护凸包;在处理叶子结点时,沿着它到根的路径在所有节点上的凸包进行二分,得到的所有答案中取最大值。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std; int read() {
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]; int head[maxn<<2], ToT, nxt[maxn*maxlog], need[maxn*maxlog];
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() {
n = read(); a = read(); b = read(); c = read();
L = read(); R = read();
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;
}

[OJ#15]TR #2 画心的更多相关文章

  1. 南阳理工OJ 15 括号匹配

    思路:动态规划,设dp[i][j]表示第i个字符到第j个字符所需要的最少匹配数,则:(1),如果从第i到j-1个字符中没有一个与第j个字符匹配,那么状态转移方程为 dp[i][j] = dp[i][j ...

  2. LeetCode OJ 15. 3Sum

    题目 Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all ...

  3. JQuery easyUI DataGrid 创建复杂列表头(译)

    » Create column groups in DataGrid The easyui DataGrid has ability to group columns, as the followin ...

  4. HTML学习(二)进阶篇

    在博客园中有许多大神对HTML超文本标记语言写了很多内容,总结了很多知识,这里对我看到的博客文章, 所学到的知识,做一个总结.  一)列表和表格 dl→definition list(定义列表),见备 ...

  5. 七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理

    第三天我们将学习Asp.Net中数据处理功能,了解数据访问层,EF,以及EF中常用的代码实现方式,创建数据访问层和数据入口,处理Post数据,以及数据验证等功能. 系列文章 七天学会ASP.NET M ...

  6. 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递

    通过第一天的学习之后,我们相信您已经对MVC有一些基本了解. 本节所讲的内容是在上节的基础之上,因此需要确保您是否掌握了上一节的内容.本章的目标是在今天学习结束时利用最佳实践解决方案创建一个小型的MV ...

  7. 通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用

    REFERENCE FROM : http://www.cnblogs.com/artech/archive/2012/07/04/Knockout-web-api.html 较之面向最终消费者的网站 ...

  8. 中软培训第一周复习总结 --简单的HTML 与CSS

    一些需要记住的点: day1 HTML格式及简单标签: html 文件一般格式: 1 <html> 2 <head lang="en"> 3 <met ...

  9. table sorting–angularjs

    1: <script type="text/javascript" ng:autobind 2: src="http://code.angularjs.org/0. ...

随机推荐

  1. TortoiseGit和git bash冲突解决

    软件版本 TortoiseGit版本: TortoiseGit 2.5.0.0 (C:\Program Files\TortoiseGit\bin) git version 2.8.1.windows ...

  2. CPP-网络/通信:gsoap 的教程和使用

    1.1.1     gSOAP 1.1.1 .1      简介 gSOAP 编译工具提供了一个 SOAP/XML 关于 C/C++ 语言的实现,从而让 C/C++ 语言研发 web 服务或客户端程式 ...

  3. OO作业第三单元总结

    目录 一.JML语言理论基础及应用工具链 二.部署JMLUnitNG,自动生成测试用例 三.架构设计 第一次作业 第二次作业 第三次作业 四.Bug分析 五.心得体会 一.JML语言理论基础及应用工具 ...

  4. 使用jquery.ajax实现省市的二级联动(SSH架构)

    首先实现jquery ajax的二级联动 要下载个jquery.js 我在这里就不准备了 自行百度下载 背景介绍:通过部门的ID来查找部门下的所有班级 我实现二级联动的思路是:先查询所有部门 显示在页 ...

  5. NOIP模拟赛 魔方

    [题目描述] ccy(ndsf)觉得手动复原魔方太慢了,所以他要借助计算机. ccy(ndsf)家的魔方都是3*3*3的三阶魔方,大家应该都见过. (3的“顺时针”改为“逆时针”,即3 4以图为准.) ...

  6. [BZOJ] 1520: [POI2006]Szk-Schools

    费用流解决. abs内传不了int..CE一次 #include<iostream> #include<cstring> #include<cstdio> #inc ...

  7. Flask-基本原理与核心知识

    虚拟环境 使用pipenv创建一个虚拟环境和项目绑定,安装:E:\py\qiyue\flask>python3 -m pip install pipenv 和项目绑定:到项目的目录中pipenv ...

  8. Java-JFrame可视化开发

    Java-JFrame可视化开发的一般步骤 JFrame可以做出类似于QQ登录功能的窗体,通过JFrame可以利用Java代码实现窗体功能,一般用于CS项目的C(客户端)的开发: 利用JFrame可以 ...

  9. Python分布式爬虫开发搜索引擎 Scrapy实战视频教程

    点击了解更多Python课程>>> Python分布式爬虫开发搜索引擎 Scrapy实战视频教程 课程目录 |--第01集 教程推介 98.23MB |--第02集 windows下 ...

  10. linux文件属性文文件类型知识

    文件类型分别介绍: 1.普通文件:我们通过用ls  -l来查看xxx.sql的属性,可以看到第一列内容为-rw-r--r--,值得注意的是第一个符号是-(英文字符减号),在Linux中,以这样的字符开 ...