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. VPN指定某个程序,其实是改路由表(赛风支持VPN和SSH和SSH+模式)

    其实就是使用IE代理的意思,方法有很多.最简单的就是读取注册表中的代理信息.具体找;\Software\Microsoft\Windows\CurrentVersion\Internet Settin ...

  2. sudo service memcached start

    我安装后memcached后,并使用 ? 1 sudo service memcached start

  3. 执行shell脚本提示“syntax error near unexpected token for((i=0;i&lt;$length;i++))”

    sh脚本例如以下: #!/usr/bin/env bash county="3 4 5 6 7 8 9 10 11 12 16 29 39 44 53 62 72 84 97 115 128 ...

  4. ASM - 条件判断

    技术交流,DH讲解. 正式之前,我们看看寄存器和CPU的标志位: OD中的截图,下方的CPAZSTDO就是标志位. Delphi的FPU窗口,右边一列就是标志位.为什么要给大家看标志位呢?因为ASM中 ...

  5. Winfrom设置DataGridView单元格获得焦点(DataGridView - CurrentCell)

    设置DataGridView单元格获得焦点 this.dgv_prescription.BeginEdit(true);

  6. Makefile自动生成工具-----autotools的使用(详细)

    相信每个学习Linux的人都知道Makefile,这是一个很有用的东西,但是编写它是比较复杂,今天介绍一个它的自动生成工具,autotools的使用.很多GNULinux的的软件都是用它生成Makef ...

  7. C++学习之路—多态性与虚函数(二)纯虚函数与抽象类

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 1    纯虚函数 在前面的博客中已经提到:有时 ...

  8. 利用iframe技巧获取訪问者qq

    今天工作时,有个暂时加的好友问我,怎么利用web页面获取訪问者的qq. 曾经没有接触过,感觉到非常好奇,可是工作中脑子非常亢奋,转的快,利用所学的知识迅速想到一条技巧,那就是假想用户在进入我们设定的页 ...

  9. 序列化TList of objects(摘自danieleteti的网站)

    Some weeks ago a customer asked to me if it is possibile serialize a TList of objects. “Hey, you sho ...

  10. Delphi的TService的輸入桌面切換(服务程序)(windows登录界面如何截图)(使用了OpenDesktop和GetThreadDesktop等API)

    dfm: object CopyDeskService: TCopyDeskService  OldCreateOrder = False  OnCreate = ServiceCreate  OnD ...