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.

  1. o o o o o o o o o o o o o o o o o o
  2. /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\ /F\
  3. / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \

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:

  1. o o o | o o o o | o o o o o o | o o o o o
  2. /F\ /F\ /F\ | /F\ /F\ /F\ /F\ | /F\ /F\ /F\ /F\ /F\ /F\ | /F\ /F\ /F\ /F\ /F\
  3. / \ / \ / \ | / \ / \ / \ / \ | / \ / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \

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
  1. 2
  2. 5 2
  3. 1 4 3 2 5
  4. 5 2
  5. 5 4 3 2 1
 
Sample Output
  1. Case #1: 31
  2. 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]
的每一个人的身高都是比自己矮的?  能够进行先排序。让矮的人先选,假设身高一样就让序号在后的先选,这样就不会有冲突了(单点更新的时候)。 每次查询的时候单点更新就可以。
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <vector>
  5. #include <algorithm>
  6. using namespace std;
  7. #define REP(_,a,b) for(int _=(a); _<=(b);++_)
  8. #define sz(s) (int)((s).size())
  9. typedef long long ll;
  10. const int maxn = 1e5+10;
  11. int n,l;
  12. ll dp[maxn];
  13. struct Num{
  14. ll h;
  15. int idx;
  16. Num(ll h = 0,int idx = 0):h(h),idx(idx){}
  17. friend bool operator < (Num a,Num b){
  18. if(a.h!=b.h) return a.h < b.h;
  19. else return a.idx > b.idx;
  20. }
  21. };
  22. vector<Num> vN;
  23. struct node{
  24. int lson,rson;
  25. ll maxx;
  26. int mid(){
  27. return (lson+rson)>>1;
  28. }
  29. }tree[maxn*4];
  30. void pushUp(int rt){
  31. tree[rt].maxx = max(tree[rt<<1].maxx,tree[rt<<1|1].maxx);
  32. }
  33.  
  34. void build(int L,int R,int rt){
  35. tree[rt].lson = L;
  36. tree[rt].rson = R;
  37. tree[rt].maxx = -1;
  38. if(L==R){
  39. return;
  40. }
  41. int mid = tree[rt].mid();
  42. build(L,mid,rt<<1);
  43. build(mid+1,R,rt<<1|1);
  44. }
  45. void init(){
  46. vN.clear();
  47. memset(dp,-1,sizeof dp);
  48. }
  49. void update(int pos,int l,int r,int rt,ll x){
  50. if(l==r){
  51. tree[rt].maxx = x;
  52. return;
  53. }
  54. int mid = tree[rt].mid();
  55. if(pos<=mid){
  56. update(pos,l,mid,rt<<1,x);
  57. }else{
  58. update(pos,mid+1,r,rt<<1|1,x);
  59. }
  60. pushUp(rt);
  61. }
  62. ll query(int L,int R,int l,int r,int rt){
  63. if(L <=l && R >= r){
  64. return tree[rt].maxx;
  65. }
  66. int mid = tree[rt].mid();
  67. ll ret;
  68. bool flag = false;
  69. if(L <= mid){
  70. ret = query(L,R,l,mid,rt<<1);
  71. flag = true;
  72. }
  73. if(R > mid){
  74. if(flag){
  75. ret = max(ret,query(L,R,mid+1,r,rt<<1|1));
  76. }else{
  77. ret = query(L,R,mid+1,r,rt<<1|1);
  78. }
  79. }
  80. return ret;
  81. }
  82. void input(){
  83. scanf("%d%d",&n,&l);
  84. REP(_,1,n){
  85. ll h;
  86. scanf("%I64d",&h);
  87. vN.push_back(Num(h,_));
  88. }
  89. sort(vN.begin(),vN.end());
  90. build(0,n,1);
  91. }
  92. void solve(){
  93. update(0,0,n,1,0);
  94. REP(_,0,sz(vN)-1) {
  95. int ni = vN[_].idx;
  96. ll nh = vN[_].h;
  97. ll tm = query(max(ni-l,0),ni-1,0,n,1);
  98. if(tm>=0){
  99. dp[ni] = tm+nh*nh;
  100. update(ni,0,n,1,dp[ni]-nh);
  101. }
  102. if(ni==n) break;
  103. }
  104. if(dp[n]<=0){
  105. printf("No solution\n");
  106. }else{
  107. printf("%I64d\n",dp[n]);
  108. }
  109. }
  110. int main(){
  111. int ncase,T=1;
  112. cin >> ncase;
  113. while(ncase--){
  114. init();
  115. input();
  116. printf("Case #%d: ",T++);
  117. solve();
  118. }
  119. return 0;
  120. }

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. linux配置ssh+rsync

    ssh  远程登录 sftp    文件共享 类似ftp  ssh  secure file transfer client scp    文件共享 类似cp   ssh配置文件 /etc/ssh/s ...

  2. 利用FFT 计算生成离散解析信号

    通常我们用到的信号都是实值信号,但是我们可以根据这个实信号构造出一个复信号,使得这个复信号只包含正频率部分,而且这个复信号的实部正好就是我们原来的实值信号.简单的推导可知,复信号的虚部是原信号的希尔伯 ...

  3. 双绞线的制作,T568A线序,T568B线序

    双绞线的制作 1.1 实验目的 双绞线是组建局域网时常常使用的通信传输介质,通过本实验,让学生学会制作双绞线. 1.2 实验任务 (1)了解双绞线的特性及屏蔽与非屏蔽双绞线的区别. (2)了解EIA/ ...

  4. [转]java-Three Rules for Effective Exception Handling

    主要讲java中处理异常的三个原则: 原文链接:https://today.java.net/pub/a/today/2003/12/04/exceptions.html Exceptions in ...

  5. asp.net2.0安全性(2)--用户个性化设置(1)--转载来自车老师

    在Membership表中可以存储一些用户的基本信息,但有的时候,我们需要记录的用户信息远远不止Membership表中提供的这些,如QQ.MSN.家庭住址.联系电话等等.那如何把这些用户信息记录到数 ...

  6. 让office2003和office2010共存的方法【转】

    前段时间由于工作需要安装office2010,每次打开word都会弹出安装配置界面,反之亦然.于是我在网上找了不少资料.也试了不少方法,终于试用了以下方法得以解决,以下来源于网络. 电脑上同时安装了O ...

  7. javascript 学习资料网址一览

    1.http://www.runoob.com/ 2.https://developer.mozilla.org/zh-CN/ 3.http://www.imooc.com/   视频类

  8. xcode6 中增加SDWebImage/SDWebImageDownloaderOperation.m报错解决方法

    报错报错:Use of undeclared identifier '_executing' / '_finished': 解决方法例如以下:

  9. 向服务器写入错误日志-log

    /// <summary> /// 写日志,方便测试(看网站需求,也可以改成把记录存入数据库) /// </summary> /// <param name=" ...

  10. Windows 8 动手实验系列教程 实验5:进程生命周期管理

    动手实验 实验5:进程生命周期管理 2012年9月 简介 进程生命周期管理对构建Windows应用商店应用的开发者来说是需要理解的最重要的概念之一.不同于传统的Windows应用(它们即使在后台仍然继 ...