题目大意

  有\(n\)个士兵(\(1 \leq n \leq 10^5\)),第\(i\)个士兵的身高为\(h_{i}\),现在要求把士兵按照原来的顺序分成连续的若干组,要求每组的士兵数量不超过\(len\)。

  同时,我们设每组的最后一个士兵的身高为\(b_{i}\),则有\(b_{i} > b_{i - 1}\)(\(b_0 = 0\)),现在我们设每种分组方案的价值为\(\sum b_{i}^2 - b_{i - 1}\),求能得到的最大价值为多少?

题解

  我们设\(dp[i]\)表示前\(i\)个士兵分成任意组的最大价值,容易得到:

\[dp[i] = \underset{i - len \leq j < i}{\max} \{ dp[j] + k_{i}^2 - k_{j} \}
\]

  整理一下,得到:

\[dp[i] = k_{i}^2 + \underset{i - len \leq j < i}{\max} \{ dp[j] - k_{j} \}
\]

  我们可以用线段树来维护\(\underset{i - len \leq j < i}{\max} \{ dp[j] - k_{j} \}\).

  但是。如何保证题目中要求的\(b_{i} > b_{i - 1}\)呢?

  其实,对于每个士兵,我们可以先按照身高来进行升序排列,如果身高相同,我们就按照编号(原来的顺序)降序排列,然后对于排序后的士兵\(i\),我们设他原来的编号为\(idx_{i}\),则我们就查找线段树上\([idx_{i} - len, idx_{i} - 1]\)的价值,同时更新也是更新线段树上的\(idx_{i}\)的位置。

  因为对于每个士兵\(i\),如果在排序前能找到和他进行状态转移的士兵\(j\),那么排序后,肯定有\(idx_{j} \in [idx_{i} - len, idx_{i} - 1]\),这个大家可以自己试几个情况,所以这样做即可。

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm> #define MAX_N (100000 + 5)
#define SIZE (1 << 21) #define lowbit(x) ((x) & -(x))
#define Getchar() (p1 == p2 && (p2 = (p1 = fr) + fread(fr, 1, SIZE, stdin), p1 == p2) ? EOF : *p1++) using namespace std; char fr[SIZE], * p1 = fr, * p2 = fr; void Read(int & res)
{
res = 0;
char ch = Getchar();
while(!isdigit(ch)) ch = Getchar();
while(isdigit(ch)) res = res * 10 + ch - '0', ch = Getchar();
return;
} struct Node
{
int h;
int idx;
friend inline bool operator < (Node a, Node b)
{
if(a.h != b.h) return a.h < b.h;
return a.idx > b.idx;
}
}; int T;
int n, len;
Node a[MAX_N];
long long s[MAX_N << 2]; void Modify(int x, int l, int r, int pos, long long val)
{
if (r < pos || pos < l) return;
if (l == r)
{
s[x] = val;
return;
}
int mid = l + r >> 1;
Modify(x << 1, l, mid, pos, val);
Modify(x << 1 | 1, mid + 1, r, pos, val);
s[x] = max(s[x << 1], s[x << 1 | 1]);
return;
} long long Query(int x, int l, int r, int L, int R)
{
if (r < L || R < l) return -0x7f7f7f7f7f7f7f7f;
if (L <= l && r <= R) return s[x];
int mid = l + r >> 1;
return max(Query(x << 1, l, mid, L, R), Query(x << 1 | 1, mid + 1, r, L, R));
} int main()
{
Read(T);
for (int I = 1; I <= T; ++I)
{
memset(s, -0x7f, sizeof s);
Read(n); Read(len);
for (int i = 1; i <= n; ++i)
{
Read(a[i].h);
a[i].idx = i;
}
sort(a + 1, a + n + 1);
long long tmp;
printf("Case #%d: ", I);
Modify(1, 0, n, 0, 0);
for (int i = 1; i <= n; ++i)
{
tmp = Query(1, 0, n, max(0, a[i].idx - len), a[i].idx - 1);
if (tmp < -0x7f7f7f7f)
{
if (a[i].idx == n)
{
printf("No solution\n");
break;
}
continue;
}
if (a[i].idx == n)
{
printf("%lld\n", (long long)a[i].h * a[i].h + tmp);
break;
}
Modify(1, 0, n, a[i].idx, (long long)a[i].h * a[i].h + tmp - a[i].h);
}
}
return 0;
}

【题解】Oh My Holy FFF的更多相关文章

  1. HDU4719-Oh My Holy FFF(DP线段树优化)

    Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) T ...

  2. HDU 4719 Oh My Holy FFF(DP+线段树)(2013 ACM/ICPC Asia Regional Online ―― Warmup2)

    Description N soldiers from the famous "*FFF* army" is standing in a line, from left to ri ...

  3. hdu4719 Oh My Holy FFF 线段树维护dp

    题意:给你一个长度为n的数组v,你需要把这个数组分成很多段,你需要保证每一段的长度不能超过k我们设一共有m段,每一段右边界那个数为bi那么我们要使得sum(bi*bi-b(i-1))最大 (1< ...

  4. hdu4719 Oh My Holy FFF 线段树优化dp

    思路 好久之前的了,忘记什么题目了 可以到我这里做luogu 反正就是hdu数据太水,导致自己造的数据都过不去,而hdu却A了 好像是维护了最大值和次大值,然后出错的几率就小了很多也许是自己写错了,忘 ...

  5. HDU 4719Oh My Holy FFF 线段树+DP

    /* ** 日期: 2013-9-12 ** 题目大意:有n个数,划分为多个部分,假设M份,每份不能多于L个.每个数有一个h[i], ** 每份最右边的那个数要大于前一份最右边的那个数.设每份最右边的 ...

  6. 2013 ACM/ICPC Asia Regional Online —— Warmup2

    HDU 4716 A Computer Graphics Problem 水题.略 HDU 4717 The Moving Points 题目:给出n个点的起始位置以及速度矢量,问任意一个时刻使得最远 ...

  7. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  8. 华南师大 2017 年 ACM 程序设计竞赛新生初赛题解

    题解 被你们虐了千百遍的题目和 OJ 也很累的,也想要休息,所以你们别想了,行行好放过它们,我们来看题解吧... A. 诡异的计数法 Description cgy 太喜欢质数了以至于他计数也需要用质 ...

  9. 洛谷 P2194 HXY烧情侣【Tarjan缩点】 分析+题解代码

    洛谷 P2194 HXY烧情侣[Tarjan缩点] 分析+题解代码 题目描述: 众所周知,HXY已经加入了FFF团.现在她要开始喜(sang)闻(xin)乐(bing)见(kuang)地烧情侣了.这里 ...

随机推荐

  1. shell之文本过滤(正则表达式)

    shell之文本过滤(正则表达式) 分类: linux shell脚本学习2012-09-14 12:59 213人阅读 评论(0) 收藏 举报 当从一个文件或命令输出中抽取或过滤文本时,可以使用正则 ...

  2. 原创——Nginx基础

    Nginx基础 一.Nginx概述: Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx ...

  3. logback系列二:logback在项目中的应用

    1.输出http日志 2.输出dubbo日志 3.输出interfacer日志 4.输出到access,remote,app等目录中

  4. k-means原理和python代码实现

    k-means:是无监督的分类算法 k代表要分的类数,即要将数据聚为k类; means是均值,代表着聚类中心的迭代策略. k-means算法思想: (1)随机选取k个聚类中心(一般在样本集中选取,也可 ...

  5. for-in语句和with语句、break和continue语句

    for-in语句 for-in语句是一种精准迭代语句,可以用来枚举对象的属性,用以遍历一个对象的全部属性. for…in声明用于对数组或者对象的属性进行循环操作: for…in循环中的代码每执行一次, ...

  6. Linux GDB 程序调试工具使用详解

    转自    http://www.codeceo.com/article/linux-gdb-tools.html 整理的挺全的 GDB概述 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试 ...

  7. ViewContainerRef 动态创建视图

    Angular DOM 操作 相关的APIs和类: 查询DOM节点 template variable ref: 模版变量引用,相当于react中的ref ViewChild: 查询DOM,返回单个元 ...

  8. Mysql数据库表类型

    MySQL的数据表类型很多,其中比较重要的是MyISAM,InnoDB这两种. 这两种类型各有优缺点,需要根据实际情况选择适合的,MySQL支持对不同的表设置不同的类型.下面做个对比:   MyISA ...

  9. TCP学习笔记

    TCP/IP 协议分层模型 TCP/IP 协议族按层次分别分为以下 4 层:应用层.传输层.网络层和数据链路层.层次化之后,每个层级只需要考虑自己的任务就可以了,不再需要弄清其他层级的功能了. TCP ...

  10. CF1081G Mergesort Strikes Back

    题目大意: 给定\(n\),\(k\),\(mod\),求随机排列在\(k\)层归并排序下逆序对的期望. 题解 考虑这\(k\)层归并会把序列分成若干个块. 这些块内的顺序是原序列的相对顺序,我们要把 ...