2012年4月2日
摘要: POJ_3378 如果设f[i][j]表示第i个数选a[j]时的方案数,那么f[i][j]就等于所有满足a[k]<a[j]的f[i-1][k]之和,为了能够快速的求出这个和,可以在循环i-1的时候就将所有的f[i-1][k]放到线段树、树状数组或者平衡树上去即可。如果用线段树或者树状数组统计的话,需要将a[]的值离散化。 此外,在计算中间结果时5000^4是不会超long long的,但是最后合并的时候需要用到高精度加法。#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXD 阅读全文
posted @ 2012-04-02 19:05 Staginner 阅读(328) 评论(0) 推荐(0) 编辑
摘要: POJ_3017 这个题目动规的方程是很好写出来的f[i]=min{f[j]+max[j+1,i]},其中j要满足sum[j+1,i]<=M。 如果裸着做的话显然是O(N^2)的复杂度,而动规的维数显然是一维,不能再减了,于是我们要试图减少决策的数量,换句话说对于每个i,我们要在O(1)或者O(logN)或者同级别的时间复杂度内找到最优的决策(decision)j,直接令f[i]=f[j]+max[j+1,i]。 先不说别的,这个max要怎么求呢?RMQ问题固然可以预处理出来,但实际上没必要那么麻烦,我们可以维护一个单调队列,对于当前的a[i],先将队尾小于或等于a[i]的元素删掉,再把 阅读全文
posted @ 2012-04-02 13:12 Staginner 阅读(2077) 评论(4) 推荐(3) 编辑
摘要: POJ_3580 更多splay练手的题目可以参考胡浩的博客http://www.notonlysuccess.com/index.php/splay-tree/,有了前面对区间翻转、切割的训练之后,这个题目就显得思路比较直观了。 对于ADD操作,和线段树的处理是一样的,加一个add延迟标记即可,在pushdown的时候别忘记还会影响到子树上记录的min值就OK了。 对于REVERSE操作,用一个rev延迟标记即可,注意到pushdown的时候子树中rev的标记应该是加1模2,而不能简单的赋值成1就OK了。 对于REVOLVE操作,实际上相当于把一个区间挪到了另一个区间后面,于是先把要移动的. 阅读全文
posted @ 2012-04-02 00:43 Staginner 阅读(535) 评论(1) 推荐(1) 编辑