Oh My Holy FFF

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)

Total Submission(s): 606    Accepted Submission(s): 141

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

 o   o   o   o   o   o   o   o   o   o   o   o   o   o   o   o   o   o
/F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\
/ \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \

You, as the captain of *FFF*, want to divide them into smaller groups, but each group should still be continous in the original line. Like this:

 o   o   o  |  o   o   o   o  |  o   o   o   o   o   o  |  o   o   o   o   o
/F\ /F\ /F\ | /F\ /F\ /F\ /F\ | /F\ /F\ /F\ /F\ /F\ /F\ | /F\ /F\ /F\ /F\ /F\
/ \ / \ / \ | / \ / \ / \ / \ | / \ / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \

In your opinion, the number of soldiers in each group should be no more than L.

Meanwhile, you want your division be "holy". Since the soldier may have different heights, you decide that for each group except the first one, its last soldier(which is the rightmost one) should be strictly taller than the previous group's last soldier. That
is, if we set bi as the height of the last soldier in group i. Then for i >= 2, there should be bi > bi-1.

You give your division a score, which is calculated as , b0 = 0 and 1 <= k <= M, if there are M groups in total. Note that M can equal to 1.

Given the heights of all soldiers, please tell us the best score you can get, or declare the division as impossible.

 
Input
The first line has a number T (T <= 10) , indicating the number of test cases.

For each test case, first line has two numbers N and L (1 <= L <= N <= 105), as described above.

Then comes a single line with N numbers, from H1 to Hn, they are the height of each soldier in the line, from left to right. (1 <= Hi <= 105)
 
Output
For test case X, output "Case #X: " first, then output the best score.
 
Sample Input
2
5 2
1 4 3 2 5
5 2
5 4 3 2 1
 
Sample Output
Case #1: 31
Case #2: No solution
 
题意:n(n < 1e5)个人排成一行,把它切成若干堆。要求每一堆的长度不超过l(l < 1e5),而且每一堆的最右一个人的身高都要比前一堆的最右一个人的身高要高,对于每一种方案,它的分数是SUM(b[k]^2-b[k-1] )  b[k] 为第k堆最右一个人的身高 要求最高的分数。

思路:朴素的DP 是  DP[i]  = max(DP[j] - b[j]) + b[i]*b[i]  ( i-l <=  j <= i-1 )  可是这样会超时(O(n^2)) 能够发现每次求DP[i] 的时候 实际就是求 区间[i-l,i-1]  DP[j]-b[j]的最大值,因此能够利用线段树优化。此时还须要解决一个问题:就是怎样保证每次求DP[i]的时候保证区间[i-l,i-1]
的每一个人的身高都是比自己矮的?  能够进行先排序。让矮的人先选,假设身高一样就让序号在后的先选,这样就不会有冲突了(单点更新的时候)。 每次查询的时候单点更新就可以。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define REP(_,a,b) for(int _=(a); _<=(b);++_)
#define sz(s) (int)((s).size())
typedef long long ll;
const int maxn = 1e5+10;
int n,l;
ll dp[maxn];
struct Num{
ll h;
int idx;
Num(ll h = 0,int idx = 0):h(h),idx(idx){}
friend bool operator < (Num a,Num b){
if(a.h!=b.h) return a.h < b.h;
else return a.idx > b.idx;
}
};
vector<Num> vN;
struct node{
int lson,rson;
ll maxx;
int mid(){
return (lson+rson)>>1;
}
}tree[maxn*4];
void pushUp(int rt){
tree[rt].maxx = max(tree[rt<<1].maxx,tree[rt<<1|1].maxx);
} void build(int L,int R,int rt){
tree[rt].lson = L;
tree[rt].rson = R;
tree[rt].maxx = -1;
if(L==R){
return;
}
int mid = tree[rt].mid();
build(L,mid,rt<<1);
build(mid+1,R,rt<<1|1);
}
void init(){
vN.clear();
memset(dp,-1,sizeof dp);
}
void update(int pos,int l,int r,int rt,ll x){
if(l==r){
tree[rt].maxx = x;
return;
}
int mid = tree[rt].mid();
if(pos<=mid){
update(pos,l,mid,rt<<1,x);
}else{
update(pos,mid+1,r,rt<<1|1,x);
}
pushUp(rt);
}
ll query(int L,int R,int l,int r,int rt){
if(L <=l && R >= r){
return tree[rt].maxx;
}
int mid = tree[rt].mid();
ll ret;
bool flag = false;
if(L <= mid){
ret = query(L,R,l,mid,rt<<1);
flag = true;
}
if(R > mid){
if(flag){
ret = max(ret,query(L,R,mid+1,r,rt<<1|1));
}else{
ret = query(L,R,mid+1,r,rt<<1|1);
}
}
return ret;
}
void input(){
scanf("%d%d",&n,&l);
REP(_,1,n){
ll h;
scanf("%I64d",&h);
vN.push_back(Num(h,_));
}
sort(vN.begin(),vN.end());
build(0,n,1);
}
void solve(){
update(0,0,n,1,0);
REP(_,0,sz(vN)-1) {
int ni = vN[_].idx;
ll nh = vN[_].h;
ll tm = query(max(ni-l,0),ni-1,0,n,1);
if(tm>=0){
dp[ni] = tm+nh*nh;
update(ni,0,n,1,dp[ni]-nh);
}
if(ni==n) break;
}
if(dp[n]<=0){
printf("No solution\n");
}else{
printf("%I64d\n",dp[n]);
}
}
int main(){
int ncase,T=1;
cin >> ncase;
while(ncase--){
init();
input();
printf("Case #%d: ",T++);
solve();
}
return 0;
}

HDU4719-Oh My Holy FFF(DP线段树优化)的更多相关文章

  1. [USACO2005][POJ3171]Cleaning Shifts(DP+线段树优化)

    题目:http://poj.org/problem?id=3171 题意:给你n个区间[a,b],每个区间都有一个费用c,要你用最小的费用覆盖区间[M,E] 分析:经典的区间覆盖问题,百度可以搜到这个 ...

  2. UVA-1322 Minimizing Maximizer (DP+线段树优化)

    题目大意:给一个长度为n的区间,m条线段序列,找出这个序列的一个最短子序列,使得区间完全被覆盖. 题目分析:这道题不难想,定义状态dp(i)表示用前 i 条线段覆盖区间1~第 i 线段的右端点需要的最 ...

  3. zoj 3349 dp + 线段树优化

    题目:给出一个序列,找出一个最长的子序列,相邻的两个数的差在d以内. /* 线段树优化dp dp[i]表示前i个数的最长为多少,则dp[i]=max(dp[j]+1) abs(a[i]-a[j])&l ...

  4. 完美字符子串 单调队列预处理+DP线段树优化

    题意:有一个长度为n的字符串,每一位只会是p或j.你需要取出一个子串S(注意不是子序列),使得该子串不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数.如果你的子串是最长的,那 ...

  5. hdu3698 Let the light guide us dp+线段树优化

    http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java ...

  6. 题解 HDU 3698 Let the light guide us Dp + 线段树优化

    http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java ...

  7. 【uva1502/hdu4117-GRE Words】DP+线段树优化+AC自动机

    这题我的代码在hdu上AC,在uva上WA. 题意:按顺序输入n个串以及它的权值di,要求在其中选取一些串,前一个必须是后一个的子串.问d值的和最大是多少. (1≤n≤2×10^4 ,串的总长度< ...

  8. Contest20140906 ProblemA dp+线段树优化

    Problem A 内存限制 256MB 时间限制 5S 程序文件名 A.pas/A.c/A.cpp 输入文件 A.in 输出文件 A.out 你有一片荒地,为了方便讨论,我们将这片荒地看成一条直线, ...

  9. POJ 3171.Cleaning Shifts-区间覆盖最小花费-dp+线段树优化(单点更新、区间查询最值)

    Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4721   Accepted: 1593 D ...

随机推荐

  1. Java进阶02 异常处理

    链接地址:http://www.cnblogs.com/vamei/archive/2013/04/09/3000894.html 作者:Vamei 出处:http://www.cnblogs.com ...

  2. Java7新特性(一)Coin

    1.语法糖 数字下划线   2.switch语句中的String   3.multicatch   4.final重抛 对比上份代码   5.try-with-resources(TWR) AutoC ...

  3. Linux下安装配置词典GoldenDict

    GoldenDict   apt-get install goldendict 安装完成以后,需要自己手动加入字典,增加在线翻译网址(例如,有道,金山等),点击 编辑--dictionaries  完 ...

  4. Vistual Studio 2012更换皮肤

    早就装上VS2012了,可是除了在家里练习玩玩的时候使用外,在公司都还在用2010,也没好好研究过2012.这两天把公司的电脑换了系统,也就把vs换成了2012.可是看着不是白白的皮肤就是深色的皮肤, ...

  5. Cocos2d-x游戏的场景结构布局

  6. linux环境 :Linux 共享库LIBRARY_PATH, LD_LIBRARY_PATH 与ld.so.conf

    参考: 1. Linux 共享库:LD_LIBRARY_PATH 与ld.so.conf Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径.(该路径在默 ...

  7. 浅析js的执行顺序

    javascript是一种描述型的脚本语言,是一种解析语言,由浏览器动态解析,不同种类的浏览器不同版本的浏览器对于js的解析有着微小的差别,不同浏览器的js解析引擎效率也有高低,下面来给大家分析一下j ...

  8. cocos2d-x 精灵移动

    在HelloWorldScene.h中声明 class  HelloWorld :  public  cocos2d::CCLayer { public :     ......     CCPoin ...

  9. Google App Engine 学习和实践

    这个周末玩了玩Google App Engine,随手写点东西,算是学习笔记吧.不当之处,请多多指正. 作者:liigo,2009/04/26夜,大连 原创链接:http://blog.csdn.ne ...

  10. pygame编写贪吃蛇

    一直想用pygame做一个小游戏的,可是因为拖延症的缘故一直没有动,结果那天看到了一个12岁的国际友人小盆友用pygame做的一款塔防游戏,突然感觉已经落后超级远了,所以心血来潮做小游戏了.高中陪伴我 ...