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

题解:
我们设数组下标从1开始
dp[i]表示:对于v数组的前i个数的最大sum(bi*bi-b(i-1))为dp[i]
dp转移方程:
dp[i]=dp[j]+v[i]*v[i]-v[j] (i>j且v[i]>v[j])
dp转移方程很容易找到,但是如果对于一个i,我们去寻找所有满足条件的j的话就该TLE了

那么我们可以使用线段树进行维护,维护第i个位置的值为dp[i]-v[i]。这样的话对于一个j(j>i)
我们只需要在线段树的[1,j-1]区间查找出来最大的值就可以了
对于查找出来的值我们只需要加上v[j]*v[j]就是dp[j]的值(这一点很重要,可以说就是把维护的值改变了一下)

但是我们发现题目还要求v[j]>v[i],怎么办呢,我们可以对所有vi排序,按照排过序之后顺序进行线段树维护查找更新
就可以了



代码:
/*
题意:
给你一个长度为n的数组v,你需要把这个数组分成很多段,你需要保证每一段的长度不能超过k
我们设一共有m段,每一段右边界那个数为bi
那么我们要使得sum(bi*bi-b(i-1))最大 (1<=i<=m,b0=0)
你需要保证bi>b(i-1) (1<=i<=m)
sum():表示求和 题解:
我们设数组下标从1开始
dp[i]表示:对于v数组的前i个数的最大sum(bi*bi-b(i-1))为dp[i]
dp转移方程:
dp[i]=dp[j]+v[i]*v[i]-v[j] (i>j且v[i]>v[j])
dp转移方程很容易找到,但是如果对于一个i,我们去寻找所有满足条件的j的话就该TLE了 那么我们可以使用线段树进行维护,维护第i个位置的值为dp[i]-v[i]。这样的话对于一个j(j>i)
我们只需要在线段树的[1,j-1]区间查找出来最大的值就可以了
对于查找出来的值我们只需要加上v[j]*v[j]就是dp[j]的值(这一点很重要,可以说就是把维护的值改变了一下) 但是我们发现题目还要求v[j]>v[i],怎么办呢,我们可以对所有vi排序,按照排过序之后顺序进行线段树维护查找更新
就可以了
*/ #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef
long long ll;
const
int maxn=1e5+10;
const
int mod=20071027;
const
int INF=0x3f3f3f3f;
ll tree[maxn<<2],dp[maxn];
ll max(ll a,ll b)
{

if
(a<b) return b;
else return
a;
}

void
push_up(ll rt)
{

tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}

void
update(ll rt,ll L,ll R,ll pos,ll val)
{

if
(L==R)
{

tree[rt]=val;
return
;
}

ll mid=(L+R)>>1;
if
(pos<=mid) update(rt<<1,L,mid,pos,val);
else
update(rt<<1|1,mid+1,R,pos,val);
push_up(rt);
}

ll query(ll rt,ll L,ll R,ll LL,ll RR)
{

if
(LL<=L && RR>=R)
{

return
tree[rt];
}

ll mid=(L+R)>>1,ans=-1;
if
(LL<=mid) ans=max(ans,query(rt<<1,L,mid,LL,RR));
if
(RR>mid) ans=max(ans,query(rt<<1|1,mid+1,R,LL,RR));
return
ans;
}

struct
shudui
{

ll val,id;
}
v[maxn],w[maxn];
bool
cmp(shudui x,shudui y)
{

return
x.val<y.val;
}

int
main()
{

ll t,p=0;
scanf("%lld",&t);
while
(t--)
{

ll pos=0;
memset(tree,-1,sizeof(tree));
memset(dp,-1,sizeof(dp));
ll n,k;
scanf("%lld%lld",&n,&k);
if
(k==1)
{

for
(ll i=1;i<=n;++i)
scanf("%lld",&v[i].val),v[i].id=i;
ll res=v[1].val*v[1].val,flag=0;
for
(ll i=2;i<=n;++i)
{

if
(v[i].val>v[i-1].val)
{

res=(res+v[i].val*v[i].val)-v[i-1].val;
}

else

{

flag=1;
break
;
}
}

if
(flag==0)
printf("Case #%lld: %lld\n",++p,res);
else
printf("Case #%lld: No solution\n",++p);
continue
;
}

for
(ll i=2;i<=n+1;++i)
scanf("%lld",&v[i].val),v[i].id=i;
update(1,1,n,1,0);
dp[1]=v[1].val*v[1].val;
ll tmp=dp[1]-v[1].val;
sort(v+2,v+2+n,cmp);
//printf("%lld**************\n",query(1,1,n,3,4));
for(ll i=2;i<=n+1;++i)
{

if
(pos>0 && v[i].val!=v[i-1].val)
{

//printf("%lld*******\n",pos);
for(ll i=0;i<pos;++i)
{

update(1,1,n,w[i].id,w[i].val);
}

pos=0;
}

if
(v[i].id==1)
{

w[0].id=1;
w[0].val=tmp;
pos++;
continue
;
}

ll ans=query(1,1,n,max(1,v[i].id-k),v[i].id-1);
//printf("%lld %lld*****\n",ans,v[i].id);
if(ans!=-1)
{

w[pos].id=v[i].id;
w[pos].val=(ans+v[i].val*v[i].val)-v[i].val;
dp[v[i].id]=max(w[pos].val+v[i].val,dp[v[i].id]);
pos++;
}
}

if
(dp[n+1]!=-1)
printf("Case #%lld: %lld\n",++p,dp[n+1]);
else
printf("Case #%lld: No solution\n",++p);
}

return
0;
}

hdu4719 Oh My Holy FFF 线段树维护dp的更多相关文章

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

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

  2. Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)

    题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...

  3. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  4. Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp

    D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...

  5. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  6. 【BZOJ2164】采矿 树链剖分+线段树维护DP

    [BZOJ2164]采矿 Description 浩浩荡荡的cg大军发现了一座矿产资源极其丰富的城市,他们打算在这座城市实施新的采矿战略.这个城市可以看成一棵有n个节点的有根树,我们把每个节点用1到n ...

  7. 【8.26校内测试】【重构树求直径】【BFS模拟】【线段树维护DP】

    题目性质比较显然,相同颜色联通块可以合并成一个点,重新建树后,发现相邻两个点的颜色一定是不一样的. 然后发现,对于一条链来说,每次把一个点反色,实际上使点数少了2个.如下图 而如果一条链上面有分支,也 ...

  8. 2019牛客暑期多校训练营(第二场)E 线段树维护dp转移矩阵

    题意 给一个\(n\times m\)的01矩阵,1代表有墙,否则没有,每一步可以从\(b[i][j]\)走到\(b[i+1][j]\),\(b[i][j-1]\),\(b[i][j+1]\),有两种 ...

  9. Codeforces750E. New Year and Old Subsequence (线段树维护DP)

    题意:长为2e5的数字串 每次询问一个区间 求删掉最少几个字符使得区间有2017子序列 没有2016子序列 不合法输出-1 题解:dp i,p(0-4)表示第i个数匹配到2017的p位置删掉的最少数 ...

随机推荐

  1. 微信扫码支付Native方式二以及支付回调

    官方API文档https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 1.使用jar包 1 <!--微信支付 --> 2 ...

  2. 一文带你探究Sentinel的独特初始化

    摘要:本系列通过作者对Redis Sentinel源码的理解,详细说明Sentinel的代码实现方式. Redis Sentinel 是Redis提供的高可用模型解决方案.Sentinel可以自动监测 ...

  3. 详细的String源码解析

    我们常常把String类型的字符串作为HashMap的key,为什么要这样做呢? 因为String是不可变的,一旦初始化就不再改变了,如果被修改将会是一个新对象. @Test public void ...

  4. MyBatis初级实战之二:增删改查

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  5. zabbix_agent items not supported状态

    不记得自己究竟更改了什么东西,然后突然发现所有的有关mysql的监控items都变成了not supported,怎么做不行,最后在web主页把主机删除,又重新添加一下,重新添加了一下模版就好了.这究 ...

  6. 彻底搞懂MySQL为什么要使用B+树索引

    目录 MySQL的存储结构 表存储结构 B+树索引结构 B+树页节点结构 为什么要用B+树索引 二叉树 多叉树 B树 B+树 搞懂这个问题之前,我们首先来看一下,MySQL表的存储结构 MySQL的存 ...

  7. kubernets之机理概览

    一  了解kubernets的运行机理 1.1  了解架构 众所周知,kubernets的组成由2个部分组成 kubernets  平面 node节点  (工作节点) 控制平面的组成 etcd  分布 ...

  8. 20V,24V转5V,20V,24V转3.3V降压芯片,IC介绍

    常用的20V和24V转5V,3.3V的LDO稳压和DC-DC降压芯片: PW6206系列是一款高精度,高输入电压,低静态电流,高速,低压降线性稳压器具有高纹波抑制.输入电压高达40V,负载电流高达10 ...

  9. 相对论中的光速c不变,这么讲!你总能理解了吧!

    今天谈谈相对论的假设基础--光速不变,很多人都知道爱因斯坦的相对论,也知道相对论的理论基础是光速不变,即无论参考哪个参照系,光的速度都是不变的,这个很难得理解的问题.我之前看过别人的理解,也自己思考怎 ...

  10. Vue 3自定义指令开发

    本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 什么是指令(directive) 在Angular和Vue中都有Direct ...