HDU 4719 浅谈数据结构优化双关键字动态规划
2017-09-27 15:42
676 查看
世界真的很大
这两天没怎么写题了,主要在考试
今天好不容易腾出一点时间,调了一下之前剩下来的这道题
既然这周在考数据结构,我自己在做DP,那就来一点数据结构优化的DP好了
本着这样的想法做了这道题
但是由于考试一直没有时间调。。
看题先:
description:
给定一排人和他们对应的身高,让你把他们分成几段,保证每一段的末尾的人的身高单增,每一种方案有一个分数,它的分数是SUM(b[k]^2-b[k-1] ) b[k] 为第k堆最右一个人的身高 要求最高的分数。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 <= 10 5), 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 <= H i <= 10 5)
output
For test case X, output “Case #X: ” first, then output the best score.练习读一下英文吧233
首先一段序列分成几段求最大权值这种东西,还是见的多了
这样的DP方程一般都是什么f(i,j)表示前i个分成j段的最大权值什么的
那既然这道题不要求多少段,那么j这一维就可以省掉了,用f(i)来表示前i个人分成“管他多少段”的最大权值
考虑怎么转移,这个思路还是很好想,就是f(i)=max(f(j)+b(i)^2+b(j)),这样转移就好了,转移时只要保证b(i) > b(j)就行了
但是这样是n^2的,因为要枚举i和j,考虑优化
考虑动态规划用数据结构优化,只能优化“填表法”
所谓“填表法”就是每次由之前的信息来推出现在的答案,比如这道题想要知道f(i)是需要枚举其之前的f(j)的。
而对应的“刷表法”是通过现在已知的答案去更新所有由这个状态能推导到的状态的答案
只有填表法能用数据结构优化,因为数据结构所优化的只有数据的“收集”,而不是数据的“分散”。
而这道题之所以能够优化,就是因为其是填表法
用线段树或者其他数据结构保存其之前一段的f值,每次选最大的内个去更新
但是还剩一个问题
每次必须选b值比i小的j,而线段树没法在这些点里面更新最小值
这样相当于线段树选着时有两个关键字b和f,在满足第一关键字比i小的情况下,找一个f最大的
这样其实是有一个套路的,既然反正只有第一关键字满足条件的能更新,那就干脆按照第一关键字排序
然后继续更新
完整代码:
#include<stdio.h> #include<algorithm> #include<cstring> #include<iostream> using namespace std; typedef long long dnt; const int INF=0x3f3f3f3f; struct people { dnt h; int id; }ple[200010]; struct node { dnt sum; node *ls,*rs; void update() { sum=max(ls->sum,rs->sum); } }pool[4000010],*tail=pool,*root; int T,n,L; dnt f[1000010]; bool cmp(const people &a,const people &b) { if(a.h==b.h) return a.id>b.id; return a.h<b.h; } node *build(int lf,int rg) { node *nd=++tail; if(lf==rg) { nd->sum=-1; nd->ls=nd->rs=0; return nd; } int mid=(lf+rg)>>1; nd->ls=build(lf,mid); nd->rs=build(mid+1,rg); nd->update(); return nd; } void modify(node *nd,int lf,int rg,int pos,dnt delta) { if(lf==rg) { nd->sum=delta; return ; } int mid=(lf+rg)>>1; if(pos<=mid) modify(nd->ls,lf,mid,pos,delta); else modify(nd->rs,mid+1,rg,pos,delta); nd->update(); } dnt query(node *nd,int lf,int rg,int L,int R) { if(L<=lf && rg<=R) return nd->sum; int mid=(lf+rg)>>1; dnt rt=-INF; if(L<=mid) rt=max(rt,query(nd->ls,lf,mid,L,R)); if(R>mid) rt=max(rt,query(nd->rs,mid+1,rg,L,R)); return rt; } void init() { root=0; tail=pool; memset(f,-1,sizeof(f)); } int main() { scanf("%d",&T); for(int e=1;e<=T;e++) { init(); scanf("%d%d",&n,&L); for(int i=1;i<=n;i++) cin >> ple[i].h,ple[i].id=i; sort(ple+1,ple+n+1,cmp); root=build(0,n); modify(root,0,n,0,0); for(int i=1;i<=n;i++) { dnt tmp=query(root,0,n,max(0,ple[i].id-L),ple[i].id-1); if(tmp>=0) { f[ple[i].id]=ple[i].h*ple[i].h+tmp; modify(root,0,n,ple[i].id,f[ple[i].id]-ple[i].h); } if(ple[i].id==n) break ; } printf("Case #%d: ",e); if(f >0) cout << f << endl; else printf("No solution\n"); } return 0; } /* Whoso pulleth out this sword from this stone and anvil is duly born King of all England */
嗯,就是这样
相关文章推荐
- 动态规划:HDU1059-Dividing(多重背包问题的二进制优化)
- 数据结构与算法之动态规划
- HDU 2089 浅谈数位动态规划水题
- CodeVS 2245 浅谈二维线段树优化间距限制型LCS动态规划状态转移
- 动态规划DP的斜率优化 个人浅解 附HDU 3669 Cross the Wall
- hdu 3401 单调队列优化动态规划
- 动态规划原理 数据结构
- 数据结构(十二)动态规划
- Python 数据结构之动态规划
- BZOJ 1264 浅谈数据结构优化特殊形式LCS动态规划求法
- HDU 1520 浅谈简单树形动态规划
- HDU 4990 Ordered Subsequence --数据结构优化DP
- BZOJ 2006 浅谈数据结构优化贪心思路
- 数据结构(之)动态规划总结
- HDU 4990 Ordered Subsequence --数据结构优化DP
- hdu - 4323 - Magic Number - dp + 数据结构优化
- 动态数据结构-动态建立链表
- 动态规划 HDU 1176 免费馅饼
- ACM;邮局问题;动态规划;O(n3); 四边形法则可以优化,暂时没研究,等待添加;
- 动态规划专题 01背包问题详解 HDU 2546 饭卡