??xml version="1.0" encoding="utf-8" standalone="yes"?>免费一级欧美大片久久网,久久人人爽人人爽人人片av麻烦,国産精品久久久久久久http://www.shnenglu.com/MatoNo1/archive/2013/03/03/198185.htmlMato_No1Mato_No1Sun, 03 Mar 2013 07:25:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2013/03/03/198185.htmlhttp://www.shnenglu.com/MatoNo1/comments/198185.htmlhttp://www.shnenglu.com/MatoNo1/archive/2013/03/03/198185.html#Feedback0http://www.shnenglu.com/MatoNo1/comments/commentRss/198185.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/198185.html??a title="BZOJ1713" >BZOJ1713
F[i][j]=max{F[i1][j1] - (sA[i-1]-sA[i1])2 - (sB[j-1]-sB[j1])2} + A[i]*B[j], 0<=i1<i, 0<=j1<j
对这个式子进行化Q?br />F[i][j]=max{F[i1][j1] - sA[i1]2 + 2*sA[i-1]*sA[i1] - sB[j1]2 + 2*sB[j-1]*sB[j1]}+A[i]*B[j]-sA[i-1]2-sB[j-1]2
对于一l的情况Q很Ҏ(gu)处理——中间是一条直U,然而这是二l的Q对于这U?D/2D的DP方程Q要优化到O(N2)U别Q需要两步?br />注意到决{式中除了F[i1][j1]外,其它部分都要么只与i1有关Q要么只与j1有关。因此,可以把阶Di的各个状态作Z个整体,在之前得出的各个F[i][j]中,对于相同的jQ找到对于目前的iQ最优的那个决策——注意Q对于相同的j1Q里面所有与j1有关的东襉K可以先不考虑了,只考虑(F[i1][j1] - sA[i1]2 + 2*sA[i-1]*sA[i1])对于目前i的最优决{。这一步可以在q些直线形成的上凸壳中找刎ͼ且满_{单调性,可以用一个栈处理Q斜率优化)。然后,这些最优决{以j变量再组成一些直U,用栈l护它们的上凸壳Q对于每个jQ找到最优值即可?br />注意事项Q在栈中删除直线的时候,如果之前的最优决{是q个被删掉的直线Q则要将最优决{先|ؓ(f)不存在,然后再插入新直线后设为新直线。另外,要特别注意^行的情况?br />
?】LCIS
l典问题Q利用上面的分步优化思想Q很Ҏ(gu)用线D|(wi)得到一个O(N2logN)的做法?br />
??a title="[SCOI2010]股票交易 " >[SCOI2010]股票交易
F[i][j]=max{F[i-1][j], max{F[i-W-1][j-a]-A*a, F[i-W-1][j+b]+b*B}}, j<=maxP, 1<=a<=maxA, 1<=b<=maxB
注意对于相同的jQ计方法是一L(fng)Q且是一条直U(׃有范围所以其实是U段Q?br />所以,计算阶段iӞ可以?i-W-1)阶段所有的决策当成U段插入Q这些线D늚斜率都相{,因此比较好维护,只需要判断边界即可?br />
注意QNOI2011的show虽然也符合对于相同的j计算Ҏ(gu)一P但它?yu)׃能优化,因?f)它的决策是不q箋且无规律的,没有M几何性质。因此,它只能用O(N3)的算法计出所有状态?br />

Mato_No1 2013-03-03 15:25 发表评论
]]>
【AHOI2013复仇】动态凸?/title><link>http://www.shnenglu.com/MatoNo1/archive/2013/02/28/198024.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Thu, 28 Feb 2013 10:29:00 GMT</pubDate><guid>http://www.shnenglu.com/MatoNo1/archive/2013/02/28/198024.html</guid><wfw:comment>http://www.shnenglu.com/MatoNo1/comments/198024.html</wfw:comment><comments>http://www.shnenglu.com/MatoNo1/archive/2013/02/28/198024.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/MatoNo1/comments/commentRss/198024.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/MatoNo1/services/trackbacks/198024.html</trackback:ping><description><![CDATA[     摘要: 原题地址写了几天l于写出来了……Q显Ӟ我太׃Q请各位犇不要鄙视Q在有加点的情况下,动态地l护凸包Q有以下两种Ҏ(gu)Q?lt;1>l护上、下凸壳Q本沙茶采用的方法)Q凸包可以拆成上、下凸壳Q对它们分别l护。两个凸壛_按照下面定义?lt;关系Q即先x增、再y增)排序Q注意,两个凸壳的两端是相同的,均ؓ(f)整个凸包的最点与最大点Q除两端外,它们没有公共定点。以上凸壳ؓ(f)?..  <a href='http://www.shnenglu.com/MatoNo1/archive/2013/02/28/198024.html'>阅读全文</a><img src ="http://www.shnenglu.com/MatoNo1/aggbug/198024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/MatoNo1/" target="_blank">Mato_No1</a> 2013-02-28 18:29 <a href="http://www.shnenglu.com/MatoNo1/archive/2013/02/28/198024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【AHOI2013复仇】SCOI2008 着色方?/title><link>http://www.shnenglu.com/MatoNo1/archive/2012/10/24/193778.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Wed, 24 Oct 2012 06:59:00 GMT</pubDate><guid>http://www.shnenglu.com/MatoNo1/archive/2012/10/24/193778.html</guid><wfw:comment>http://www.shnenglu.com/MatoNo1/comments/193778.html</wfw:comment><comments>http://www.shnenglu.com/MatoNo1/archive/2012/10/24/193778.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/MatoNo1/comments/commentRss/193778.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/MatoNo1/services/trackbacks/193778.html</trackback:ping><description><![CDATA[<a title="原题地址" >原题地址</a><br />首先Q看q么的范围q道,数学Ҏ(gu)肯定搞不?#8230;…又想不到其它模型……只能用状压硬搞了?#8230;…<br />问题是,5^15ETQ如果能倒过来,15^5Q就不会(x)T了?br />可以发现QC值相同的颜色本质上是一L(fng)……因此Q只需要保存目前Cgؓ(f)1????的颜色各有多种p了囧……Q当然在q程中还?x)出现Cgؓ(f)0的,即用完的颜色Q不q??????的和是颜色LQ而且从下面可以看出,Cgؓ(f)0的确?#8220;木有?#8221;Q;<br />设F[s1][s2][s3][s4][s5][v]为涂完前若干个木块(q个个数可以通过s1~s5出Q不q我们ƈ不需要它?#8230;…Q后QCgؓ(f)1~5的颜色各有s1~s5U,且这若干个中?strong><span style="color: red;">最后一个涂的颜色还剩的C?/span></strong>为vQ显?<=v<=4Q?br />边界QF[S[1]][S[2]][S[3]][S[4]][S[5]][0]=1Q其余ؓ(f)0QS[i]Z开始Cgؓ(f)i的颜色种敎ͼ?br />计算FӞ前推后(注意序Q是按照S[5]逆序最先,再依ơ是S[4]~S[1]Q都是逆序Qv可Q意定序)Q枚举下一个木块的颜色是现在还剩多的Q如果它与目前的q个Q最后一个)剩的相同Q则要减1Q否则不减。具体的方程见代码?br />注意l节Q枚举F的s1~s5下标Ӟ都要NQ颜色LQ开始枚举,因ؓ(f)q程中某些sg(x)增加Q?br /><br />本题的启C就是,在设计状压DP的时候,如果正着来不行,可以反着来,或许p设计出符合要求的解法?br /><br />代码Q?br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #000000;">#include </span><span style="color: #000000;"><</span><span style="color: #000000;">iostream</span><span style="color: #000000;">></span><span style="color: #000000;"><br />#include </span><span style="color: #000000;"><</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">></span><span style="color: #000000;"><br />#include </span><span style="color: #000000;"><</span><span style="color: #000000;">stdlib.h</span><span style="color: #000000;">></span><span style="color: #000000;"><br />#include </span><span style="color: #000000;"><</span><span style="color: #0000ff;">string</span><span style="color: #000000;">.h</span><span style="color: #000000;">></span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">using</span><span style="color: #000000;"> </span><span style="color: #0000ff;">namespace</span><span style="color: #000000;"> std;<br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> re(i, n) for (int i=0; i<n; i++)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> re1(i, n) for (int i=1; i<=n; i++)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> re2(i, l, r) for (int i=l; i<r; i++)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> re3(i, l, r) for (int i=l; i<=r; i++)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> rre(i, n) for (int i=n-1; i>=0; i--)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> rre1(i, n) for (int i=n; i>0; i--)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> rre2(i, r, l) for (int i=r-1; i>=l; i--)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> rre3(i, r, l) for (int i=r; i>=l; i--)</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">#define</span><span style="color: #000000;"> ll long long</span><span style="color: #000000;"><br /></span><span style="color: #0000ff;">const</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> n </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">5</span><span style="color: #000000;">, MAXM </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">16</span><span style="color: #000000;">, MOD </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">1000000007</span><span style="color: #000000;">;<br /></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> m, S[n </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">];<br />ll F[MAXM][MAXM][MAXM][MAXM][MAXM][n], res;<br /></span><span style="color: #0000ff;">void</span><span style="color: #000000;"> init()<br />{<br />    scanf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%d</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">&</span><span style="color: #000000;">m); </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> x;<br />    re(i, m) {scanf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%d</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">&</span><span style="color: #000000;">x); S[x]</span><span style="color: #000000;">++</span><span style="color: #000000;">;}<br />}<br /></span><span style="color: #0000ff;">void</span><span style="color: #000000;"> solve()<br />{<br />    F[S[</span><span style="color: #000000;">1</span><span style="color: #000000;">]][S[</span><span style="color: #000000;">2</span><span style="color: #000000;">]][S[</span><span style="color: #000000;">3</span><span style="color: #000000;">]][S[</span><span style="color: #000000;">4</span><span style="color: #000000;">]][S[</span><span style="color: #000000;">5</span><span style="color: #000000;">]][</span><span style="color: #000000;">0</span><span style="color: #000000;">] </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">; </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> tmp;<br />    rre3(i5, m, </span><span style="color: #000000;">0</span><span style="color: #000000;">) rre3(i4, m, </span><span style="color: #000000;">0</span><span style="color: #000000;">) rre3(i3, m, </span><span style="color: #000000;">0</span><span style="color: #000000;">) rre3(i2, m, </span><span style="color: #000000;">0</span><span style="color: #000000;">) rre3(i1, m, </span><span style="color: #000000;">0</span><span style="color: #000000;">) re(v, n)<br />        </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (F[i1][i2][i3][i4][i5][v]) {<br />            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (i1) {<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (v </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">) tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i1 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">; </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i1;<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (tmp) {<br />                    F[i1 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i2][i3][i4][i5][</span><span style="color: #000000;">0</span><span style="color: #000000;">] </span><span style="color: #000000;">+=</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">*</span><span style="color: #000000;"> F[i1][i2][i3][i4][i5][v];<br />                    F[i1 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i2][i3][i4][i5][</span><span style="color: #000000;">0</span><span style="color: #000000;">] </span><span style="color: #000000;">%=</span><span style="color: #000000;"> MOD;<br />                }<br />            }<br />            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (i2) {<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (v </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #000000;">2</span><span style="color: #000000;">) tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i2 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">; </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i2;<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (tmp) {<br />                    F[i1 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i2 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i3][i4][i5][</span><span style="color: #000000;">1</span><span style="color: #000000;">] </span><span style="color: #000000;">+=</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">*</span><span style="color: #000000;"> F[i1][i2][i3][i4][i5][v];<br />                    F[i1 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i2 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i3][i4][i5][</span><span style="color: #000000;">1</span><span style="color: #000000;">] </span><span style="color: #000000;">%=</span><span style="color: #000000;"> MOD;<br />                }<br />            }<br />            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (i3) {<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (v </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #000000;">3</span><span style="color: #000000;">) tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i3 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">; </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i3;<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (tmp) {<br />                    F[i1][i2 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i3 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i4][i5][</span><span style="color: #000000;">2</span><span style="color: #000000;">] </span><span style="color: #000000;">+=</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">*</span><span style="color: #000000;"> F[i1][i2][i3][i4][i5][v];<br />                    F[i1][i2 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i3 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i4][i5][</span><span style="color: #000000;">2</span><span style="color: #000000;">] </span><span style="color: #000000;">%=</span><span style="color: #000000;"> MOD;<br />                }<br />            }<br />            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (i4) {<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (v </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #000000;">4</span><span style="color: #000000;">) tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i4 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">; </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">=</span><span style="color: #000000;"> i4;<br />                </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (tmp) {<br />                    F[i1][i2][i3 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i4 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i5][</span><span style="color: #000000;">3</span><span style="color: #000000;">] </span><span style="color: #000000;">+=</span><span style="color: #000000;"> tmp </span><span style="color: #000000;">*</span><span style="color: #000000;"> F[i1][i2][i3][i4][i5][v];<br />                    F[i1][i2][i3 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i4 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i5][</span><span style="color: #000000;">3</span><span style="color: #000000;">] </span><span style="color: #000000;">%=</span><span style="color: #000000;"> MOD;<br />                }<br />            }<br />            </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (i5) {<br />                F[i1][i2][i3][i4 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i5 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][</span><span style="color: #000000;">4</span><span style="color: #000000;">] </span><span style="color: #000000;">+=</span><span style="color: #000000;"> i5 </span><span style="color: #000000;">*</span><span style="color: #000000;"> F[i1][i2][i3][i4][i5][v];<br />                F[i1][i2][i3][i4 </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][i5 </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">][</span><span style="color: #000000;">4</span><span style="color: #000000;">] </span><span style="color: #000000;">%=</span><span style="color: #000000;"> MOD;<br />            }<br />        }<br />    res </span><span style="color: #000000;">=</span><span style="color: #000000;"> F[</span><span style="color: #000000;">0</span><span style="color: #000000;">][</span><span style="color: #000000;">0</span><span style="color: #000000;">][</span><span style="color: #000000;">0</span><span style="color: #000000;">][</span><span style="color: #000000;">0</span><span style="color: #000000;">][</span><span style="color: #000000;">0</span><span style="color: #000000;">][</span><span style="color: #000000;">0</span><span style="color: #000000;">];<br />}<br /></span><span style="color: #0000ff;">void</span><span style="color: #000000;"> pri()<br />{<br />    cout </span><span style="color: #000000;"><<</span><span style="color: #000000;"> res </span><span style="color: #000000;"><<</span><span style="color: #000000;"> endl;<br />}<br /></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> main()<br />{<br />    init();<br />    solve();<br />    pri();<br />    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />}<br /></span></div><img src ="http://www.shnenglu.com/MatoNo1/aggbug/193778.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-10-24 14:59 <a href="http://www.shnenglu.com/MatoNo1/archive/2012/10/24/193778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【AHOI2013复仇】NOI2008 道\设计http://www.shnenglu.com/MatoNo1/archive/2012/09/22/191595.htmlMato_No1Mato_No1Sat, 22 Sep 2012 08:21:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2012/09/22/191595.htmlhttp://www.shnenglu.com/MatoNo1/comments/191595.htmlhttp://www.shnenglu.com/MatoNo1/archive/2012/09/22/191595.html#Feedback0http://www.shnenglu.com/MatoNo1/comments/commentRss/191595.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/191595.html原题地址
典型的二ơ递推/DP的题目?br />首先Q题目中?#8220;不便利?#8221;指的是某个点到根的\径上的木有被选定链覆盖的边的条数?br />
W一问:(x)设F[i][0..2]分别为当子树(wi)i中结点i的状态ؓ(f)不参与链Q?Q、作为某铄点(1Q、作为某链中间点Q?Q时Q子?wi)i中的l点到i的最不便利倹{ؓ(f)了得到FQ需要设立G[j][k(0..2)]表示l点i的前j子?wi)中Q有k늚根结点与l点i接上的最的最大不便利倹{显Ӟ不和i接上的,状态ؓ(f)0??都行Q但不便利D?Q而和i接上的状态只能是0?Q不??br />
问题是第二问。第二问的难点在于,当i取得最不便利值时Qi的每个子l点q都取到最不便利?/strong>。D个例子,l点i的最不便利gؓ(f)3Q它的某个子l点j的最不便利gؓ(f)2Q则当j与i接上Ӟ子树(wi)j的内部既可以取不便利gؓ(f)2的解Q也可以取不便利gؓ(f)3的解。所以,Z解决W二问,需要求出结点i的最不便利gؓ(f)x的解的L?strong>万幸的是Qx的范围ƈ不是太大Q可以证明,x不会(x)过log3NQ下取整Q,也就是当N=100000时x最大ؓ(f)10?/span>因此Q最后仍然不?x)T掉?br />
q题的一个启C就是,在求cM?#8220;最优解计数”的问题中Q?span style="color: red">不要认ؓ(f)当后面的状态取得最优解Ӟ前面的状态一定取得最优解?/strong>因此Q不能只记录某状态取得最优解的个敎ͼ而要记录该状态取得每一个可行解时的个数?br />
代码Q?
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 100010, MAXW = 11, INF = ~0U >> 2;
struct edge {
    
int a, b, pre, next;
} E0[MAXN 
* 3], E[MAXN << 1];
int n, m0, m, Q[MAXN], F[MAXN][3], G[MAXN][3], res1 = 0;
ll MOD, FS[MAXN][MAXW][
3], S[MAXN][MAXW][3], res2 = 0;
bool vst[MAXN];
void init_d()
{
    re(i, n) E0[i].pre 
= E0[i].next = E[i].pre = E[i].next = i; m0 = m = n;
}
void add_edge0(int a, int b)
{
    E0[m0].a 
= a; E0[m0].b = b; E0[m0].pre = E0[a].pre; E0[m0].next = a; E0[a].pre = m0; E0[E0[m0].pre].next = m0++;
    E0[m0].a 
= b; E0[m0].b = a; E0[m0].pre = E0[b].pre; E0[m0].next = b; E0[b].pre = m0; E0[E0[m0].pre].next = m0++;
}
void add_edge(int a, int b)
{
    E[m].a 
= a; E[m].b = b; E[m].pre = E[a].pre; E[m].next = a; E[a].pre = m; E[E[m].pre].next = m++;
}
void init()
{
    
int _M; scanf("%d%d"&n, &_M); cin >> MOD; if (_M < n - 1) {res1 = res2 = -1return;} init_d(); int a0, b0;
    re2(i, 
1, n) {scanf("%d%d"&a0, &b0); add_edge0(--a0, --b0);}
}
void prepare()
{
    re(i, n) vst[i] 
= 0; Q[0= 0; vst[0= 1int x, y;
    
for (int front=0, rear=0; front<=rear; front++) {
        x 
= Q[front];
        
for (int p=E0[x].next; p != x; p=E0[p].next) {
            y 
= E0[p].b;
            
if (!vst[y]) {vst[y] = 1; Q[++rear] = y; add_edge(x, y);}
        }
    }
    re(i, n) 
if (!vst[i]) {res1 = -1; res2 = -1return;}
}
inline 
int minv3(int s1, int s2, int s3)
{
    
int s0 = s1 <= s2 ? s1 : s2;
    
return s0 <= s3 ? s0 : s3;
}
inline 
int minv2(int s1, int s2)
{
    
return s1 <= s2 ? s1 : s2;
}
void solve()
{
    
int x, y, len, v1, v2, v01, v02; ll sum;
    rre(i, n) {
        x 
= Q[i]; len = 0; G[0][0= 0; G[0][1= G[0][2= INF;
        
for (int p=E[x].next; p != x; p=E[p].next) {
            y 
= E[p].b; len++;
            v1 
= minv3(F[y][0], F[y][1], F[y][2]) + 1; v2 = minv2(F[y][0], F[y][1]);
            G[len][
0= v1 >= G[len - 1][0? v1 : G[len - 1][0];
            v01 
= v1 >= G[len - 1][1? v1 : G[len - 1][1];
            v02 
= v2 >= G[len - 1][0? v2 : G[len - 1][0];
            G[len][
1= minv2(v01, v02);
            v01 
= v1 >= G[len - 1][2? v1 : G[len - 1][2];
            v02 
= v2 >= G[len - 1][1? v2 : G[len - 1][1];
            G[len][
2= minv2(v01, v02);
        }
        re(j, 
3) F[x][j] = G[len][j];
        re(j, MAXW) {S[
0][j][0= 1; S[0][j][1= S[0][j][2= 0;} len = 0;
        
for (int p=E[x].next; p != x; p=E[p].next) {
            y 
= E[p].b; len++;
            re(j, MAXW) re(k, 
3) {
                S[len][j][k] 
= 0;
                
if (j) {
                    sum 
= 0; re(k0, 3) {sum += FS[y][j - 1][k0]; if (sum >= MOD) sum -= MOD;}
                    S[len][j][k] 
= (sum * S[len - 1][j][k]) % MOD;
                }
                
if (k) {
                    sum 
= 0; re(k0, 2) {sum += FS[y][j][k0]; if (sum >= MOD) sum -= MOD;}
                    S[len][j][k] 
= (S[len][j][k] + sum * S[len - 1][j][k - 1]) % MOD;
                }
            }
        }
        re(j, MAXW) re(k, 
3) FS[x][j][k] = S[len][j][k];
    }
    res1 
= minv3(F[0][0], F[0][1], F[0][2]);
    res2 
= 0; re(i, 3if (F[0][i] == res1) res2 += FS[0][F[0][i]][i]; res2 %= MOD;
}
void pri()
{
    cout 
<< res1 << endl << res2 << endl;
}
int main()
{
    init();
    
if (!res1) prepare();
    
if (!res1) solve();
    pri();
    
return 0;
}




Mato_No1 2012-09-22 16:21 发表评论
]]>
【AHOI2013复仇】两道LIS模型题ȝhttp://www.shnenglu.com/MatoNo1/archive/2012/09/08/189969.htmlMato_No1Mato_No1Sat, 08 Sep 2012 12:40:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2012/09/08/189969.htmlhttp://www.shnenglu.com/MatoNo1/comments/189969.htmlhttp://www.shnenglu.com/MatoNo1/archive/2012/09/08/189969.html#Feedback0http://www.shnenglu.com/MatoNo1/comments/commentRss/189969.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/189969.html??a title="[HAOI2007]上升序列 " >[HAOI2007]上升序列
预处理:(x)设F[i]Zi开头的最长上升序列的长度Q怎么求不用说了吧?#8230;…
假设目前需要求长度为M的、标号字典序最的上升序列Q显然其W一个元素A[i]必须满F[i]>=MQ注意,不是{于Q是大于{于Q)Q找到满个条件的最的i卛_。然后,讄前已l求Z该序列的Wx个元素ؓ(f)A[y]Q则W?x+1)个元素A[z]需要满的条g是A[z]>A[y]Q且F[z]=F[y]-1Q找到满个条件的最的z即ؓ(f)该序列的W?x+1)个元素。按照这U方法,扫描一遍就可以求出整个序列Q时间复杂度为O(N)。如果整个序列的最长上升序列长?lt;MQ则无解?br />
代码Q?
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 10010,    MAXM = 1010, INF = ~0U >> 2;
int n, m, len, A[MAXN], F[MAXN], D[MAXN], res[MAXM];
void prepare()
{
    D[len 
= 0= INF; int l, r, mid;
    rre(i, n) 
if (A[i] < D[len]) D[F[i] = ++len] = A[i]; else {
        l 
= 0; r = len;
        
while (l < r) {
            mid 
= l + r + 1 >> 1;
            
if (A[i] < D[mid]) l = mid; else r = mid - 1;
        }
        F[i] 
= l + 1; D[l + 1= A[i];
    }
}
void solve()
{
    
int x, y;
    re(i, n) 
if (F[i] >= m) {
        res[
0= A[i]; if (m == 1return; x = m - 1; y = 1;
        re2(j, i
+1, n) if (F[j] >= x && A[j] > res[y - 1]) {res[y++= A[j]; if (y == m) returnelse x--;}
    }
}
int main()
{
    scanf(
"%d"&n); re(i, n) scanf("%d"&A[i]);
    prepare();
    
int m_s; scanf("%d"&m_s);
    re(i, m_s) {scanf(
"%d"&m); if (m > len) puts("Impossible"); else {solve(); re(j, m-1) printf("%d ", res[j]); printf("%d\n", res[m - 1]);}}
    
return 0;
}


??a title="[HAOI2006]数字序列 " >[HAOI2006]数字序列
首先Q由于序列的所有元素都是整敎ͼ所以可以将原序列的所有元素减d的下标,q样把上升序列转化Z下降序列了?br />W一问的l果昄是(N-新序列的最长不下降序列长度)。关键在于第二问。以下A均表C新序列?br />设F[i]ZA[i]l尾的最长不下降序列长度Q同P求法不用说了Q,G[i]为在A[i]不修改的前提下将A[0..i]转变Z下降序列的最修攚w。首先求出F[i]Q然后在求G[i]Ӟ枚D上一?#8220;不动?#8221;Q就是不修改的元素)A[j]Q显然必LA[j]<=A[i]且F[j]=F[i]-1Q,q样最修攚w是G[j]+(A[j..i]转变Z下降序列的最修攚wQ。可以证明,A[j..i]的最优修Ҏ(gu)案必然是A[j+1..t]全部修改为A[j]QA[t+1..i]全部修改为A[i]Q这里t是一个[j..i]范围的倹{问题就是如何求出最优的tQ?br />一开始,假设t=jQ即把A[j+1..i-1]全部修改为A[i]Q计出修改量,设ؓ(f)S。然后,׃A[j+1..i-1]之间的元素要么小于A[j]Q要么大于A[i]Q这个是昄的囧Q,我们把小于A[j]的元素称?#8220;数”Q把大于A[i]的元素称?#8220;大数”Q则当t取t0Ӟ修改量ؓ(f)S-(A[i]-A[j])*(A[j+1..t0]中的“数”个数减去“大数”个数Q。这P只需扫描一下,求出使得(A[j+1..t0]中的“数”个数减去“大数”个数Q值最大的t0卛_?br />当然q有一个问题,对于同一个iQ满?#8220;A[j]<=A[i]且F[j]=F[i]-1”的元素个数可能有很多Q如果一个一个枚举,一个一个扫描,?x)很慢的?#8230;…解决Ҏ(gu)是,求出满q个条g的j中最的一个,设ؓ(f)j0Q然后把A[j0+1..i-1]中的所?#8220;数”?#8220;大数”全部处理出来Q然后用cM前缀和的Ҏ(gu)p搞了?#8230;…当然Qؓ(f)了找到j0Q需要徏一个二分图Q边?F[i], i)?br />最后,Z方便Q可以把A序列的左边加一?INFQ右边加一?INF。最后ȝ旉复杂度,理论上ؓ(f)O(N2)Q但׃是随机数据,所以远q达不到q个U别?br />
代码Q?
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 40010, INF = ~0U >> 2;
struct edge {
    
int a, b, pre, next;
} E[MAXN 
<< 1];
int n, m, A[MAXN], D[MAXN], F[MAXN], W[MAXN], res1;
ll G[MAXN], res2;
void init_d()
{
    re(i, n) E[i].pre 
= E[i].next = i; m = n;
}
void add_edge(int a, int b)
{
    E[m].a 
= a; E[m].b = b; E[m].pre = E[a].pre; E[m].next = a; E[a].pre = m; E[E[m].pre].next = m++;
}
void init()
{
    scanf(
"%d"&n);
    A[
0= -INF; re1(i, n) {scanf("%d"&A[i]); A[i] -= i;} A[++n] = INF; n++;
}
void solve()
{
    init_d(); F[
0= 0; G[0= 0; D[0= -INF; add_edge(00); int len = 0, l, r, mid, x, maxw; ll sum, tmp;
    re2(i, 
1, n) {
        
if (A[i] >= D[len]) D[F[i] = ++len] = A[i]; else {
            l 
= 0; r = len;
            
while (l < r) {
                mid 
= l + r + 1 >> 1;
                
if (A[i] >= D[mid]) l = mid; else r = mid - 1;
            }
            D[F[i] 
= ++l] = A[i];
        }
        
for (int p=E[F[i]-1].next; ; p=E[p].next) if (A[i] >= A[x = E[p].b]) break;
        W[x] 
= 0; re2(j, x+1, i) if (A[j] < A[i]) W[j] = W[j - 1+ 1else W[j] = W[j - 1- 1;
        sum 
= 0; maxw = -INF; G[i] = ~0Ull >> 2;
        rre2(j, i, x) {
            
if (A[j] <= A[i] && F[j] == F[i] - 1) {
                tmp 
= G[j] + sum; if (tmp < G[i]) G[i] = tmp;
                tmp 
= G[j] + sum - (ll) (maxw - W[j]) * (A[i] - A[j]); if (tmp < G[i]) G[i] = tmp;
            }
            
if (A[j] > A[i]) sum += A[j] - A[i]; else sum += A[i] - A[j];
            
if (W[j] > maxw) maxw = W[j];
        }
        add_edge(F[i], i);
    }
    res1 
= n - F[n - 1- 1; res2 = G[n - 1];
}
void pri()
{
    cout 
<< res1 << endl << res2 << endl;
}
int main()
{
    init();
    solve();
    pri();
    
return 0;
}




Mato_No1 2012-09-08 20:40 发表评论
]]>
炮兵阵地以及(qing)与其相关的一cȝ压DP问题http://www.shnenglu.com/MatoNo1/archive/2012/03/10/167626.htmlMato_No1Mato_No1Sat, 10 Mar 2012 15:27:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2012/03/10/167626.htmlhttp://www.shnenglu.com/MatoNo1/comments/167626.htmlhttp://www.shnenglu.com/MatoNo1/archive/2012/03/10/167626.html#Feedback0http://www.shnenglu.com/MatoNo1/comments/commentRss/167626.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/167626.html原题地址
说实话我W一ơ尝试写炮兵阵地是在2009q?#8230;…已经q去两年多了Q终于找C一个好的解?#8230;…庆祝一?#8230;…

【状态压~DP?br />所谓状态压~DPQ就是对于某些DP问题Q每一阶段的状态都有很多维Q要利用某些手段它们压~到一l_(d)一个正整数Q,Zq行状态的_Q去掉不合法的状态)Q然后再q行DP。这里讲的主要是传统的状压DPQ有一U基?#8220;插头”的DPQ更高Q以后再搞?br />对于本题Q可以设计出一个这L(fng)状态:(x)[0..1][0..1][0..1]...[0..1]Q有M个[0..1]Q,表示该行的每个格子放不放炮兵Q如果放Qؓ(f)1Q否则ؓ(f)0。显Ӟq是一个M位二q制敎ͼ如果能把它们压羃成一个int好了?br />
【如何压~?br />W一个问题是q么多维的状态如何压~的问题?br />对于本题Q由于是二进制数Q直接压~就可以了。但是对于某些情况,状态是个三q制敎ͼ每个格子的属性都?U)甚至更多q制敎ͼq样Q直接压~会(x)D无法使用位运,从而“解压”变得很麻烦,耗时也很长(需要暴力)Q因此,可以每位三q制都拆成两位二q制Q?br />0->00
1->01
2->10
Q当?拆成10?拆成11也木有问题,只要能区分开p了)
q样Q每个状态就可以?个二q制数来表示Q可以在构造出所有合法状态以后将每个状态所对应的两位二q制数存到struct里面Q用时调出卛_?br />
【如何精?br />q个问题是最重要的,因ؓ(f)Q如果不_Q在枚D状态以?qing){Uȝ时候就?x)枚丑ֈ很多不合法状态,D旉费?br />所谓精Q是指在预处理以?qing)DPq程中,量避开不合法状态?br />Q?Q预处理中的_Q?br />包括3个部分:(x)
<1>扑ֈ所有可能的合法状态ƈ~号Q根据题意限Ӟ有的状态在阶段内就不合法(比如本题Q一行一阶段Q那么凡是有两个1位的距离于2的状态都不合法)Q而且q种状态所占的比重往往q很大(本题中,M=10Ӟ也只?0U可能的合法状态)Q此ӞZ扑ֈq些合法状态,可以DFS构造实现?br />需要注意的是,有的题不光要扑ֈ一个阶D内的合法状态,q要扑ֈ两个或两个以上阶D内的合法状态(比如那个有关多米诺骨牌的题)Q此旉要两个int同时DFSQ?br />在找到合法状态以后,需要对每个合法状态进行编P以达?#8220;压羃”的目的。这里就涉及(qing)C状态编号和状态表C的问题Q比如,状?001Q表CZؓ(f)9Q在DFS中第一个被搜到Q因此编号ؓ(f)0Q不要搞混了q两个(其不要搞؜“~号?”?#8220;状态表CZؓ(f)0”Q它们是不同的)。在预处理和DP的过E中Q所有涉?qing)到状态的数组下标Q全部是~号而不是表C,知道~号要求表示Q可以在DFS中记录的数组里面调,而知道表C求编P可以利用逆数l或者哈希;
<2>扑ֈ每一阶段的合法状态:(x)即?lt;1>中被判定为合法的状态,在具体的各个阶段中也未必合法Q比如本题,如果某一行的某一个位|是'H'Q不能放Q而某一个状态在q里放了Q则不合法)Q因此要Ҏ(gu)个阶D再枚D一遍,扑ֈ真正合法的状态,q计入一个vectorQ?br /><3>扑ֈ状态{UM的合法状态:(x)在状态{UMQ往往要求状态不冲突Q比如本题,在连l的三个阶段中,都不能有某一位有两个?的情况)Q因此,q要枚D每个状态在转移时与其不冲突的状态,q计入vector?br />注意Q有时候这一步不是很Ҏ(gu)q行Q需要在DPq程中进行;
Q?QDPq程中的_Q?br />DPq程中,枚D状态、{Ud{都只枚丑֐法的Q在vector里面调(注意vector里记录的全都是状态编可(g)不是表C!Q,可以大大减少枚D量,不过有时候,q会(x)有一些时间浪费,q时候,可以采取一些其它的办法来精Q比如再ơ进行DFS构造合法状态等?br />
MQ这c问题的目标是“_Q精Q再_Q枚D到的不合法状态减到最?#8221;?br />代码Q?br />
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
#include 
<vector>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define pb push_back
#define IR iterator
typedef vector 
<int> vi;
const int MAXN = 103, MAXM = 11, MAXS = 100, INF = ~0U >> 2;
int n, m, S, A[MAXN], B[MAXS], T1[MAXS], F[MAXN][MAXS][MAXS], res;
bool F0[MAXN][MAXS];
vi P0[MAXN], P1[MAXS][MAXS];
void init()
{
     scanf(
"%d%d"&n, &m); getchar();
     re1(i, n) {A[i] 
= 0; re(j, m) A[i] |= ((getchar() == 'P'<< j); getchar();}
}
void dfs(int v, int ST)
{
    
if (v >= m) B[S++= ST; else {dfs(v + 3, ST | (1 << v)); dfs(v + 1, ST);}
}
void prepare()
{
    S 
= 0; dfs(00);
    re(i, S) {T1[i] 
= 0for (int j=B[i]; j; j-=j&(-j)) T1[i]++;}
    re1(i, n) re(j, S) 
if (!(~A[i] & B[j])) {P0[i].pb(j); F0[i][j] = 1;} P0[0].pb(S - 1); F0[0][S - 1= 1;
    re(i, S) re(j, S) 
if (!(B[i] & B[j])) re(k, S) if (!(B[i] & B[k]) && !(B[j] & B[k])) P1[i][j].pb(k);
}
void solve()
{
    re3(i, 
0, n) re(j1, S) re(j2, S) F[i][j1][j2] = -INF; F[0][S - 1][S - 1= 0;
    vi::IR vi_e0, vi_e1, vi_e2; 
int j0, j1, k, V;
    re(i, n) {
        vi_e0 
= P0[i].end(); if (i) vi_e1 = P0[i - 1].end(); else vi_e1 = P0[i].end();
        
for (vi::IR p=P0[i].begin(); p != vi_e0; p++)
            
for (vi::IR p_=P0[i ? i - 1 : i].begin(); p_ != vi_e1; p_++) {
                j0 
= *p; j1 = *p_;
                
if (!(B[j0] & B[j1])) {
                    vi_e2 
= P1[j0][j1].end();
                    
for (vi::IR p__ = P1[j0][j1].begin(); p__ != vi_e2; p__++) {
                        k 
= *p__;
                        
if (F0[i + 1][k]) {
                            V 
= F[i][j0][j1] + T1[k];
                            
if (V > F[i + 1][k][j0]) F[i + 1][k][j0] = V;
                        }
                    }
                }
            }
    }
    res 
= 0; re(i, S) re(j, S) if (F[n][i][j] > res) res = F[n][i][j];
}
void pri()
{
     printf(
"%d\n", res);
}
int main()
{
    init();
    prepare();
    solve();
    pri();
    
return 0;
}


Mato_No1 2012-03-10 23:27 发表评论
]]>
KMP、AC自动机在字符串匹配类动态规划问题中的应?/title><link>http://www.shnenglu.com/MatoNo1/archive/2011/10/30/159339.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sun, 30 Oct 2011 03:22:00 GMT</pubDate><guid>http://www.shnenglu.com/MatoNo1/archive/2011/10/30/159339.html</guid><wfw:comment>http://www.shnenglu.com/MatoNo1/comments/159339.html</wfw:comment><comments>http://www.shnenglu.com/MatoNo1/archive/2011/10/30/159339.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/MatoNo1/comments/commentRss/159339.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/MatoNo1/services/trackbacks/159339.html</trackback:ping><description><![CDATA[有一cd态规划(其中也包含递推Q问题,要求满一些限制条件的字符Ԍq些限制条g?#8220;需要含有某个子?#8221;?#8220;不能含有某个子串”Q那么KMP、AC自动机等有大用了?br /><br />【例1?a title="HDU3689" >HDU3689</a><br />题意Q字W集中有一些字W,l出每个字符的出现概率(它们的和保证?Q,再给Z个子串BQ求QQl一个长度ؓ(f)N的字W串AQ只能包含字W集中的字符Q,使得S是A的子串的概率?br /><br />求解q类问题首先要进行补集{化。因为子串可能有重叠Q比?ababa"中就出现了两?aba"Q,所以先转化?#8220;求Ql一个长度ؓ(f)N的字W串AQ只能包含字W集中的字符Q,使得<span style="color: red"><strong>B不是A的子?/strong></span>的概?#8221;Q然后再?减去q个概率即ؓ(f)l果?br />设F[i][j]?#8220;在所有长度ؓ(f)i?span style="color: red"><strong>不出现B</strong></span>的字W串中,后缀与B的前~匚w长度为jQ即该字W串的后~与B的前~?span style="color: red"><strong>最?/strong></span>匚w长度为jQ的概率”Q很昄QF是由递推得到了,关键是如何进行状态{U?或者说Q在递推q程中,哪些状态可能成为F[i][j]的前状态?<br />假设F[i-1][k]是F[i][j]的前状态,也就是说Q?span style="color: red"><strong>在字W集中至存在一个字WcQ得主串的Wi位(最后一位)取cӞ能够从F[i-1][k]转移到F[i][j]</strong></span>。这需要求一个值S[k][c]Q表C当M的后~与B的前~的(最大)匚w长度为kӞ在主串后再加上一个字WcQ其匚w长度?x)变成什么。D例:(x)讄前主串A'="abasab"QB="asabs"Q其匚w长度?Q若在A'后加上一个字W?s'Q则匚w长度变ؓ(f)5Q所以S[4]['s']=5Q而若在A'后加上一个字W?a'Q则匚w长度?x)变?Q所以S[4]['a']=1。显然S值和A前面的哪些字W是没有关系的?br />那么q个S值如何计?其实可以发现QS和KMP法中的nx数组似Q因此完全可以按照计nx数组的办法来计算S。具体来_(d)先要对B作KMP自n匚wQ求出其nx数组Q然后,在求S[k][c]的时候,试在B的第k位(׃B的下标从0开始所以B[k-1]Q后加上字符cQ看看会(x)“回退”到哪里即可。代码:(x) <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">     </span><span style="color: #0000ff">int</span><span style="color: #000000"> j </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">; nx[</span><span style="color: #000000">0</span><span style="color: #000000">] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">;<br />     re2(i, </span><span style="color: #000000">1</span><span style="color: #000000">, m) {<br />            </span><span style="color: #0000ff">while</span><span style="color: #000000"> (j </span><span style="color: #000000">&&</span><span style="color: #000000"> A[i] </span><span style="color: #000000">!=</span><span style="color: #000000"> A[j]) j </span><span style="color: #000000">=</span><span style="color: #000000"> nx[j </span><span style="color: #000000">-</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000">];<br />            </span><span style="color: #0000ff">if</span><span style="color: #000000"> (A[i] </span><span style="color: #000000">==</span><span style="color: #000000"> A[j]) j</span><span style="color: #000000">++</span><span style="color: #000000">;<br />            nx[i] </span><span style="color: #000000">=</span><span style="color: #000000"> j;<br />     }<br />     re(i, m) re(k, SZ) {<br />           j </span><span style="color: #000000">=</span><span style="color: #000000"> i;<br />           </span><span style="color: #0000ff">while</span><span style="color: #000000"> (j </span><span style="color: #000000">&&</span><span style="color: #000000"> A[j] </span><span style="color: #000000">!=</span><span style="color: #000000"> k </span><span style="color: #000000">+</span><span style="color: #000000"> </span><span style="color: #000000">97</span><span style="color: #000000">) j </span><span style="color: #000000">=</span><span style="color: #000000"> nx[j </span><span style="color: #000000">-</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000">];<br />           </span><span style="color: #0000ff">if</span><span style="color: #000000"> (A[j] </span><span style="color: #000000">==</span><span style="color: #000000"> k </span><span style="color: #000000">+</span><span style="color: #000000"> </span><span style="color: #000000">97</span><span style="color: #000000">) S[i][k] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">++</span><span style="color: #000000">j; </span><span style="color: #0000ff">else</span><span style="color: #000000"> S[i][k] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000">;<br />     }</span></div>q里m是B的长度。注意,当i=mӞS[i][j]是无意义的,因ؓ(f)前面已经说过了不能出现B?br />在求出S值后p求出Fg。对于状态F[i][j]Q若存在一个字Wc使得x=S[i][c]Q满?<=x<mQ,则F[i][j]是F[i+1][x]的前状态。当Ӟ׃本题是求概率而不是求LQ且每个字符出现的概率还不一P所以{Uȝ时候,应是F[i+1][x]加上F[i][j]*P[c]QP[c]是字Wc出现的概率)Q边界:(x)F[0][0]=1QF[0][1..m-1]均ؓ(f)0?br />最l结果ؓ(f)1-∑F[N][0..m-1]?br /><br /><a title="代码" >代码</a><br /><br />【例2?a title="PKU1625" >PKU1625</a>Q?a title="URAL1158" >URAL1158</a>Q?br />题意Q给Z些子Ԍ求长度ؓ(f)NQ各个字W都属于l定的字W集的所有字W串中,不包含Q何一个给出的子串的字W串个数Q需要用压9位的高精度)?br /><br />本题昄是【例1】的多子串Ş式,而用来解军_个字W串同时匚w的只有AC自动机,那么如何在本题中使用AC自动机求解呢Q?br />观察【例1】中的F[i][j]Q可以想象一下,一个图中有m个顶点,分别表示匚w长度?..(m-1)Q然后不断新加入的字W让q些状态在q些l点间不断{U(状态{Ud是图中的边)Q这PF[i][<span>j]pC?#8220;阶段i到达l点j?#8221;。而AC自动</span><span>机是ZTrieQ树(wi)Q的Q?/span><span>其中有现?/span><span>的结</span><span>点,q就揭示了本题的?/span><span>?/span><span><strong>Q?/strong></span><br /><span>F[i][j]</span><span>?/span><span>C?/span><strong><span style="color: #ff0000">长度为i的合法的字符Ԍ是满字符集限制且不包含Q何一个给定子Ԍ中,在匹配到最后一位(</span></strong><strong style="color: #ff0000">Wi位)后,刚好到达l点j的字W串?/strong><strong style="color: #ff0000">个数</strong>?br />同样QS[k][c]表示“目前到达l点kQ接下来的一个字W是c的时候,?x)到辑֓个结炏V在Ҏ(gu)有的子串建立了自动机之后QS值只要类似地搞就能求出来了。然后F的{UM搞定了?br />不过Q本题要万分注意AC自动机的一个BUGQ在建立了自动机以后Q需要把所有本w不危险Q如果一个结点代表的字符串刚好是某一个给出的不能出现的子Ԍ则该l点是危险结点)Q但通过p|指针不断上溯能够到达一个危险结点的l点Q也标记为危险结点,比如两个子串?abcde"?bc"Q则代表"abcd"的那个结点由于包含了"bc"所以也是危险的?br />此外Q本题的输入要注意,字符集的ASCII码范围是-128~127Q所以必ȝchar而不是unsigned charQ且׃可能包含I格所以必ȝgets()而不是scanf()输入Q又因ؓ(f)C/C++中木有负C标,因此在输入之后还要{化一下(?28Q?br /><br /><a title="代码" >代码</a><br /><br />【例3?a title="PKU3691" >PKU3691</a><br />题意Q给Z些子串和一个字W串AQ其每个字符均属于字W集{'A', 'C', 'G', 'T'}Q,求至要改动A的几个字W(不能Ҏ(gu)不属于字W集的字W)Q得它不包含Q何一个给出的子串Q若不管怎么攚w不行Q则l果?1?br /><br />q就是真正的DP了。设F[i][j]为前i位,到达的结点ؓ(f)jQ最改动的字符个数Q则转移方程?br />F[i][j] = min{F[i-1][x] + (A[i] != c)}Qc∈{'A', 'C', 'G', 'T'}QS[x][c]=j。边界:(x)F[0][root]=0Q其余的F[0][]=+∞QA的实际下标从1开始?br />求S数组的方法见【例2?br /><br /><a title="代码" >代码</a><br /><br />【例4?a title="PKU3208" >PKU3208</a><br />题意Q含有连l的三个数字6的正整数Q称?beastly number"Q求WP个(1<=P<=50000000Q?beastly number"Q其位数不会(x)过15位)?br />Q这题是本沙茶在PKU上至今ؓ(f)止,自己惛_法的AC人数最的题)<br />本题其实是用不着KMP的,因ؓ(f)"666"q样单的子串……<br /><br />思\Q由于位C?x)超q?5位(后来发现最多只?0位)Q所以每?beastly number"都可以看成一个长度ؓ(f)15Q字W集为['0'..'9']的字W串Q注意是可以有前?的,因ؓ(f)位数可能不15位)AQ整个过E也是从高位(W?位)向低位(W?4位)求出A的各位?br /><br />预处理:(x)求出F[i][j]Q表CA的前i位已l确定(其中不含"666"Q准来说是非末不?666"Q,且前i位的末尾刚好有j?6'Qj的范围是0?Q时Q有多少?beastly number"Q注意,前i位既然已l确定,׃可更改了Q能够决定的只有Wi位的后面Q?br />昄先要求出F0[i][j]表示有多个不是"beastly number"。其递推方程不好写,见代码(其实也是很好理解的)。然后F[i][j]=10<sup>14-i</sup> - F0[i][j]?br /><br />然后是不断调整边界来构造了。准来_(d)讑։i-1位已l确定,现在要确定第i位,则枚丄i位是0~9中的哪个|然后求出满条g的最的"beastly number"和最大的"beastly number"的名ơ(注意Q名ơ是?开始的Q,看看P在不在其中,q样p定了。严重注意:(x)如果已确定的位数中已l出C"666"Q接下来的就不用枚D了,直接在后面接上P-Lp了,L为左边界?br /><br />但是Qؓ(f)什么要把本题放在KMP的专题里面呢囧?<span>因ؓ(f)如果q个子串不是"666"而是一些结构复</span><span>杂的东东比如"123131"q样的,只有借助K</span><span>MP法了。这ӞF[i][j]pC?A的前i位已l确定(非末不含这个子ԌQ且其后~与这个子串的前缀?/span><span>配长度ؓ(f)</span><span>jQ?/span>有多个"beastly number" Q{ULE与前几个例子类伹{?br /><br /><a title="代码" >代码</a><br /><br />ȝQ?br />KMP法和AC自动机的状态{UL质军_了它们在字符串匹配类DP问题中的巨大作用。在实际应用中,要注意灵zM用它们。此外,AC自动机的那个BUG是一定要注意的?<img src ="http://www.shnenglu.com/MatoNo1/aggbug/159339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/MatoNo1/" target="_blank">Mato_No1</a> 2011-10-30 11:22 <a href="http://www.shnenglu.com/MatoNo1/archive/2011/10/30/159339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PKU3017http://www.shnenglu.com/MatoNo1/archive/2011/07/08/150454.htmlMato_No1Mato_No1Fri, 08 Jul 2011 04:40:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2011/07/08/150454.htmlhttp://www.shnenglu.com/MatoNo1/comments/150454.htmlhttp://www.shnenglu.com/MatoNo1/archive/2011/07/08/150454.html#Feedback1http://www.shnenglu.com/MatoNo1/comments/commentRss/150454.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/150454.html【原题见q里?br />
本沙茶见q的最猥琐的DP题啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊?#8230;…

设F[i]为将A[1..i]拆分成若q段的最大值最和Q则?br />F[i]=min{F[j] + max[j+1, i]}QB[i]<=j<iQ,其中max[j+1, i]表示A[j+1..i]中的最大|B[i]表示从i向左最q可以g伸到哪里Q也是满SUM[x..i]<=m的最的x|。B数组可以通过预处理在O(N)旉内得到?br />边界QF[0]=0?br />
下面是优化过E。JZP犇的论文里面已l够详细了。这里只是简要说明一下?br />首先Ҏ(gu)证明QF是单调递增的?br />然后一个很关键的定理是Q?strong style="color: red">若F[i]的最优决{ؓ(f)jQ则有A[j]>∀A[k]Qj<k<=iQ?/strong>
证明Q用反证法。若A[j+1..i]中存在不于A[j]的|则可得max[j..i]=max[j+1..i]Q又因ؓ(f)F单调递增Q所以F[j-1]+max[j..i]<=F[j]+max[j+1.i]Q即决策(j-1)一定不比决{j差,也就是决{j不可能成为最优决{?br />q样Q可以维护一个下标严格递增、Ag格递减的队列QQ即对于队列中的L两个元素Q[i]和Q[j]Q若i<jQ则Q[i].pos<Q[j].pos且A[Q[i].pos]>A[Q[j].pos]Q具体实现时pos可省略)。则可能成ؓ(f)最优决{的决策要么是在q个队列Q里,要么是B[i]。对于队列中的某个决{Q[x]Q该决策导出的gؓ(f)F[Q[x]]+A[Q[x + 1]]Q很Ҏ(gu)证明max[Q[x]+1..i]=A[Q[x + 1]]Q,扑ֈq些导出的g的最值即可(注意Q队օ素没有导出|。对于决{B[i]Q只需要在预处理的时候同时得到MAX[i]=max[B[i]+1..i]卛_Q也可以在O(N)旉内得刎ͼQ决{B[i]导出的gؓ(f)F[B[i]]+MAX[i]?br />在删除队首过时元素的时候,需要把导出g删除Q删除队օ素也一P插入的时候,若插入前队列不ؓ(f)I,则需要插入一个导出倹{也是Q需要一个支持在Ҏ(gu)旉内进行插入、删除Q意结炏V找最值等操作Q显然用q?wi)最好?br />
注意事项Q?br />Q?Q不是在队首删除还是在队尾删除Q若删除的是队列中的最后一个元素,则不需要在q?wi)中删除导出|
Q?Q插入时Q若插入前队列ؓ(f)I,则不需要在q?wi)中插入导出|
Q?Q在计算F[i]Ӟ应先决{i压入?br />
代码Q?
#include <iostream>
#include 
<stdio.h>
using namespace std;
#define re1(i, n) for (int i=1; i<=n; i++)
const int MAXN = 100001;
struct node {
    
int l, r, p, sz0, sz, mul;
    
long long v;
} T[MAXN];
const long long INF = ~0Ull >> 2;
int n, N = 0, a[MAXN], b[MAXN], MAX[MAXN], Q[MAXN], front = 0, rear = -1, root = 0;
long long m, F[MAXN], res = 0;
void init()
{
    cin 
>> n >> m;
    re1(i, n) scanf(
"%d"&a[i]); a[0= ~0U >> 2;
}
void prepare()
{
    re1(i, n) 
if (a[i] > m) {res = -1return;}
    
int x = 1;
    
long long sum = 0;
    re1(i, n) {
        
for (sum+=a[i]; sum>m; sum-=a[x++]) ;
        b[i] 
= x - 1;
    }
    re1(i, n) {
        
for (; front<=rear && Q[front]<=b[i]; front++) ;
        
for (; front<=rear && a[Q[rear]]<=a[i]; rear--) ;
        Q[
++rear] = i; MAX[i] = a[Q[front]];
    }
}
void vst(int x)
{
    
if (x) {
        cout 
<< T[x].v << ' ';
        vst(T[x].l); vst(T[x].r);
    }
}
void slc(int _p, int _c)
{
    T[_p].l 
= _c; T[_c].p = _p;
}
void src(int _p, int _c)
{
    T[_p].r 
= _c; T[_c].p = _p;
}
void upd(int x)
{
    T[x].sz0 
= T[T[x].l].sz0 + T[T[x].r].sz0 + T[x].mul;
    T[x].sz 
= T[T[x].l].sz + T[T[x].r].sz + 1;
}
void lrot(int x)
{
    
int y = T[x].p;
    
if (y == root) T[root = x].p = 0else {int p = T[y].p; if (y == T[p].l) slc(p, x); else src(p, x);}
    src(y, T[x].l); slc(x, y); T[x].sz0 
= T[y].sz0; T[x].sz = T[y].sz; upd(y);
}
void rrot(int x)
{
    
int y = T[x].p;
    
if (y == root) T[root = x].p = 0else {int p = T[y].p; if (y == T[p].l) slc(p, x); else src(p, x);}
    slc(y, T[x].r); src(x, y); T[x].sz0 
= T[y].sz0; T[x].sz = T[y].sz; upd(y);
}
void maintain(int x, bool ff)
{
    
int z;
    
if (ff) {
        
if (T[T[T[x].r].r].sz > T[T[x].l].sz) {z = T[x].r; lrot(z);}
        
else if (T[T[T[x].r].l].sz > T[T[x].l].sz) {z = T[T[x].r].l; rrot(z); lrot(z);} else return;
    } 
else {
        
if (T[T[T[x].l].l].sz > T[T[x].r].sz) {z = T[x].l; rrot(z);}
        
else if (T[T[T[x].l].r].sz > T[T[x].r].sz) {z = T[T[x].l].r; lrot(z); rrot(z);} else return;
    }
    maintain(T[z].l, 
0); maintain(T[z].r, 1); maintain(z, 0); maintain(z, 1);
}
int find(long long _v)
{
    
int i = root;
    
long long v0;
    
while (i) {
        v0 
= T[i].v;
        
if (_v == v0) return i; else if (_v < v0) i = T[i].l; else i = T[i].r;
    }
    
return 0;
}
int Find_Kth(int K)
{
    
int i = root, s0, m0;
    
while (1) {
        s0 
= T[T[i].l].sz0; m0 = T[i].mul;
        
if (K <= s0) i = T[i].l; else if (K <= s0 + m0) return i; else {K -= s0 + m0; i = T[i].r;}
    }
}
void ins(long long _v)
{
    
if (!root) {
        T[
++N].v = _v; T[N].l = T[N].r = T[N].p = 0; T[N].sz0 = T[N].sz = T[N].mul = 1; root = N;
    } 
else {
        
int i = root, j;
        
long long v0;
        
while (1) {
            T[i].sz0
++; v0 = T[i].v;
            
if (_v == v0) {T[i].mul++return;} else if (_v < v0) j = T[i].l; else j = T[i].r;
            
if (j) i = j; else break;
        }
        T[
++N].v = _v; T[N].l = T[N].r = 0; T[N].sz0 = T[N].sz = T[N].mul = 1if (_v < v0) slc(i, N); else src(i, N);
        
while (i) {T[i].sz++; maintain(i, _v > T[i].v); i = T[i].p;}
    }
}
void del(int x)
{
    
if (T[x].mul > 1) {
        T[x].mul
--while (x) {T[x].sz0--; x = T[x].p;}
    } 
else {
        
int l = T[x].l, r = T[x].r, p;
        
if (l && r) {
            
int y; while (y = T[l].r) l = y;
            T[x].v 
= T[l].v; T[x].mul = T[l].mul; p = T[l].p;
            
if (l == T[p].l) slc(p, T[l].l); else src(p, T[l].l);
            
while (p) {upd(p); p = T[p].p;}
        } 
else {
            
if (x == root) T[root = l + r].p = 0else {p = T[x].p; if (x == T[p].l) slc(p, l + r); else src(p, l + r); while(p) {upd(p); p = T[p].p;}}
        }
    }
}
long long h(int x)
{
    
return F[Q[x]] + a[Q[x + 1]];
}
void solve()
{
    F[
0= 0; front = 0; rear = 0; Q[0= 0;
    re1(i, n) {
        
for (; front<=rear && Q[front]<b[i];) {if (front < rear) del(find(h(front))); front++;}
        
for (; front<=rear && a[Q[rear]]<=a[i];) {if (front < rear) del(find(h(rear - 1))); rear--;}
        Q[
++rear] = i; if (front < rear) ins(h(rear - 1));
        
if (root) F[i] = T[Find_Kth(1)].v; else F[i] = INF;
        
if (F[b[i]] + MAX[i] < F[i]) F[i] = F[b[i]] + MAX[i];
    }
    res 
= F[n];
}
void pri()
{
    cout 
<< res << endl;
}
int main()
{
    init();
    prepare();
    
if (!res) solve();
    pri();
    
return 0;
}



Mato_No1 2011-07-08 12:40 发表评论
]]>
多重背包问题的单调队列优?/title><link>http://www.shnenglu.com/MatoNo1/archive/2011/07/05/150231.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Tue, 05 Jul 2011 10:00:00 GMT</pubDate><guid>http://www.shnenglu.com/MatoNo1/archive/2011/07/05/150231.html</guid><wfw:comment>http://www.shnenglu.com/MatoNo1/comments/150231.html</wfw:comment><comments>http://www.shnenglu.com/MatoNo1/archive/2011/07/05/150231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/MatoNo1/comments/commentRss/150231.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/MatoNo1/services/trackbacks/150231.html</trackback:ping><description><![CDATA[多重背包问题朴素旉复杂度ؓ(f)O(NMS)Q这里S是所有物品的数量s之和Q,l过二进制优化后旉复杂度ؓ(f)O(NMlog2S)Q这个复杂度已经能够应付大多数题了,但对于某些特别卡旉的题Q比如N*M=10<sup>7</sup>?Q仍然会(x)TLE。这Ӟ可以用单调队列优化,旉复杂度降为O(NM)?br /><br />首先看一下多重背包问题的朴素转移方程Q?br />F[i][j] = max{F[i-1][j-x*w[i]]+x*v[i]} (0<=x<=s[i], j>=x*w[i])<br />如果使用滚动数组Q忽略iq一l_(d)设w0=w[i]Qv0=v[i]Qs0=s[i]Q得Q?br />F[j] = max{F[j-x*w0]+x*v0} (0<=x<=s0, j>=x*w0)<br />看上去这和单调队列木有神马关p,因ؓ(f)决策下标Qj-x*w0Q不是一个整数区_(d)中间是有间隔的。然而可以发玎ͼq个方程的限制条?#8220;0<=x<=s0Qj>=x*w0”Q也是x的下界是max{0, j/w0Q下取整Q}Q当j单调递增Ӟq个下界也是单调递增的。这满单调队列优化的条件中?#8220;决策下标的下界单?#8221;……不是Q还不能q样_(d)因ؓ(f)q里的决{下标是j-x*w0Q而不是x?br />那么怎样才可以把决策下标变ؓ(f)xQ?br /><br />决{下标按照模w0的余数进行分c,可以分成w0c,分别对应模w0?、余1……?w0-1)的情c(din)这Ӟ上面方程中的所有决{下标j-x*w0都是同一cȝ。进一步,设q =j/w0Q下取整Q,r=j%w0Q则j=q*w0+rQ对于某个决{下标j'Q设k=(j'-r)/w0Q即j'=k*w0+r。显然可以发玎ͼk的取D围是Qk>=0且q-s0<=k<=qQ也即k的下界是max{0, q-s0}——随j的单调而单调?br />然后Q{ULE可以改为(q里把r当成一个已知量了)Q?br />F[q*w0+r] = max{F[k*w0+r]+(q-k)*v0} (k>=0且q-s0<=k<=q)<br />即F[q*w0+r]=max{F[k*w0+r]-k*v0}+q*v0 (k>=0且q-s0<=k<=q)<br />设G[k]=F[k*w0+r]得:(x)<br />G[q]=max{G[k]-k*v0}+q*v0 (k>=0且q-s0<=k<=q)<br />q个方程已经可以使用单调队列来优化了Q?br /><br />q样可以得出法Q?br />Q?Q从1到nQ枚举iQ徏立w[i]个空的单调队列,每个队列的元素都是两个int|(x)(k, val)Q表C{换后下标和决{?G[k]-k*v[i])Q?br />Q?Q从0到mQ枚举jQ得出q、r的|对于队列rQ?br />?】删去队首过Ӟk<q-m[i]Q的元素Q?br />?】F[j]入队Q这里的F[j]指上一阶段的F[j]Q即F[i-1][j]。因此这一步操作一定要先进行)Q删去队所有决{值val不大?F[j]-q*v[i])的元素?br />?】取出队首结点,其val值加上q*v[i]后即为本阶段F[j]的倹{?br />最后F[m]即ؓ(f)l果。L间复杂度为O(NM)?br /><br />其实q个是可以推q的Q即对于如下形式的{ULE(其中H、G和W(xu)均ؓ(f)帔RQB[i]为决{下标的下界Q随i单调Q:(x)<br />F[i] = opt{F[i-x*H+W]}+G (B[i]<=i-x*H+W<iQx∈<strong>N</strong>Q?br />都可以用上述的办法进行{化,从而进行单调队列优化?br /> <img src ="http://www.shnenglu.com/MatoNo1/aggbug/150231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/MatoNo1/" target="_blank">Mato_No1</a> 2011-07-05 18:00 <a href="http://www.shnenglu.com/MatoNo1/archive/2011/07/05/150231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.cn-ppg.cn" target="_blank">þþþƷһ</a>| <a href="http://www.jandown.cn" target="_blank">þþþùƷ鶹ARӰԺ</a>| <a href="http://www.wrene.com.cn" target="_blank">þþþþþƷο </a>| <a href="http://www.u18718.cn" target="_blank">þþþƷSmվ</a>| <a href="http://www.gawagapu.cn" target="_blank">þƵ</a>| <a href="http://www.cn1s.cn" target="_blank">AVþþƷ</a>| <a href="http://www.hdmi-cable.cn" target="_blank">ھƷþ޻</a>| <a href="http://www.xh80.cn" target="_blank">žžþþƷ</a>| <a href="http://www.sohucn.com.cn" target="_blank">69ƷþþþAPP</a>| <a href="http://www.matory.cn" target="_blank">þ99ھƷ</a>| <a href="http://www.uazm.cn" target="_blank">þ99Ʒһ</a>| <a href="http://www.panroad.cn" target="_blank">ڵСþþþþþ</a>| <a href="http://www.xinkecheng.net.cn" target="_blank">þҹɫƷ</a>| <a href="http://www.jytextile.cn" target="_blank">ŷƷۺϾþ</a>| <a href="http://www.zesf.com.cn" target="_blank">þseƷһƷ</a>| <a href="http://www.site5d.cn" target="_blank">þĻ</a>| <a href="http://www.yzx777.cn" target="_blank">ƷžžþƵ</a>| <a href="http://www.thinkct.com.cn" target="_blank">Ļþ2017</a>| <a href="http://www.zynsbank.cn" target="_blank">99Ʒþþþþþ</a>| <a href="http://www.sxjax.cn" target="_blank">ݺɫþþһ</a>| <a href="http://www.63552277.cn" target="_blank">ƷþþþþҰ</a>| <a href="http://www.gofiv.cn" target="_blank">޹Ʒþһ</a>| <a href="http://www.wolfgroup.com.cn" target="_blank">91Ʒ91Ⱦþþþø</a>| <a href="http://www.psia.cn" target="_blank">Ļһþ</a>| <a href="http://www.dartools.cn" target="_blank">Ʒŷ޺ձþ</a>| <a href="http://www.73sd.cn" target="_blank">ղƷþþþþþ</a>| <a href="http://www.acesolo.cn" target="_blank">ĻƷþ</a>| <a href="http://www.binzhun.cn" target="_blank">뾫Ʒþþþ </a>| <a href="http://www.jiaokuaidi.cn" target="_blank">þþƷ</a>| <a href="http://www.zg-ly.cn" target="_blank">þþþùһ</a>| <a href="http://www.fzmnls.cn" target="_blank">þݹֻƬ</a>| <a href="http://www.jfhtgj.cn" target="_blank">þþþòҰ¸߳</a>| <a href="http://www.68360.cn" target="_blank">þԭav</a>| <a href="http://www.lkmheatlock.com.cn" target="_blank">ݺɫۺϾþ</a>| <a href="http://www.yc-shop.cn" target="_blank">ҹŷƷþþþþþ</a>| <a href="http://www.xiaohaa.cn" target="_blank">þþۺϾɫۺϾ</a>| <a href="http://www.77ns.cn" target="_blank">ھƷþþþþþӰ鶹 </a>| <a href="http://www.rydtw.cn" target="_blank">ھƷѾþӰԺ</a>| <a href="http://www.jjj41.cn" target="_blank">ƷҹþøƬ</a>| <a href="http://www.lanqie.com.cn" target="_blank">þþƷҹҹҹҹҹþ</a>| <a href="http://www.omqw.cn" target="_blank">Ʒ99þþþþ鶹</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>