??xml version="1.0" encoding="utf-8" standalone="yes"?>久久精品成人免费观看97,久久久久青草线蕉综合超碰 ,色婷婷综合久久久久中文字幕http://m.shnenglu.com/MatoNo1/archive/2013/08/31/202905.htmlMato_No1Mato_No1Sat, 31 Aug 2013 15:39:00 GMThttp://m.shnenglu.com/MatoNo1/archive/2013/08/31/202905.htmlhttp://m.shnenglu.com/MatoNo1/comments/202905.htmlhttp://m.shnenglu.com/MatoNo1/archive/2013/08/31/202905.html#Feedback1http://m.shnenglu.com/MatoNo1/comments/commentRss/202905.htmlhttp://m.shnenglu.com/MatoNo1/services/trackbacks/202905.html阅读全文

Mato_No1 2013-08-31 23:39 发表评论
]]>
【AHOI2013复仇】再看HDU2871http://m.shnenglu.com/MatoNo1/archive/2012/11/25/195647.htmlMato_No1Mato_No1Sun, 25 Nov 2012 06:54:00 GMThttp://m.shnenglu.com/MatoNo1/archive/2012/11/25/195647.htmlhttp://m.shnenglu.com/MatoNo1/comments/195647.htmlhttp://m.shnenglu.com/MatoNo1/archive/2012/11/25/195647.html#Feedback0http://m.shnenglu.com/MatoNo1/comments/commentRss/195647.htmlhttp://m.shnenglu.com/MatoNo1/services/trackbacks/195647.html原题地址
本沙茶去q曾l用双线D|(wi)的方法捉了这题(详见q里Q,最q重新审视这题发玎ͼ借助q?wi),可以得到更简单的Ҏ(gu)?br />
题目大意Q?br />有一个长度ؓ(f)N的内存条Q每个位|的状态有占用和不占用两种Q有4U操作:(x)
Q?QResetQ清I所有内存(卛_所有位|的状态改Z占用Q删除所有内存块Q;
Q?QNew xQ申请一个新的内存块Q即扑ֈ一个长度ؓ(f)x的连l不占用位置区间Q将它们标记为占用,若有多个q样的区_(d)取最左边的,若木有输出Reject NewQ?br />Q?QFree xQ在已申L(fng)内存块中Q找到包含位|x的ƈ释放Q将该内存块删除Q同时其占用的所有位|改Z占用Q,若木有内存块包含位置xQ则输出Reject FreeQ?br />Q?QGet xQ找出已甌的内存块中,左vWx个,q输出其左端点;若已甌的内存块数目不x个,则输出Reject Get?br />
可以发现Q每个已l申L(fng)内存块尽代表一D区_(d)但仍然是独立的单位,因此Q可以把内存块当成结点,用^衡树(wi)l护Q关键字为内存块的左端点位置Q,New操作中内存块的插入与Free操作中内存块的删除均在此q?wi)内q行QReset操作只需要将整棵?wi)销毁即可?br />问题是,在New操作中,需要找C个长度ؓ(f)x的连l不占用区间Q而连l的不占用区间ƈ不是独立的单位,因此需要用线D|(wi)l护。在U段?wi)中Q需要维?lt;1>l点区间内最长连l不占用块的长度Q?lt;2>l点区间左端、右端连l不占用块的长度Q否则无法维?lt;1>Q;同时Q由于在New操作中需要区间整体改占用QFree操作中又需要区间整体改不占用,所以应当支持整体改值的标记Q对于Reset操作Q只需要全部位|改不占用即可(不能重新建树(wi)Q!Q;

q样Q利用一^衡树(wi)加一늺D|(wi)Q就可以得到一个很单的Ҏ(gu)了(代码量是双^衡树(wi)或双U段?wi)的一半左叻IQ?br />
q题的启C是Q在解决数据l构l计c题的时候,到底选用什么样的数据结构,是有讲究的,因ؓ(f)它将直接影响到编E复杂度。一般来_(d)U段?wi)比q?wi)好写,但是?gu)题而言Q双U段?wi)反而不如^衡树(wi)加线D|(wi)好写Q这是因为对于内存块使用q?wi)维护比使用U段?wi)维护更好。在以后做这U题的时候,要多想一下,扑ֈ便方法?br />

Mato_No1 2012-11-25 14:54 发表评论
]]>
l于?x)写动态树(wi)?/title><link>http://m.shnenglu.com/MatoNo1/archive/2012/02/26/166547.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sun, 26 Feb 2012 05:03:00 GMT</pubDate><guid>http://m.shnenglu.com/MatoNo1/archive/2012/02/26/166547.html</guid><wfw:comment>http://m.shnenglu.com/MatoNo1/comments/166547.html</wfw:comment><comments>http://m.shnenglu.com/MatoNo1/archive/2012/02/26/166547.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://m.shnenglu.com/MatoNo1/comments/commentRss/166547.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/MatoNo1/services/trackbacks/166547.html</trackback:ping><description><![CDATA[【背景?br />2012q??9日,本沙茶开始看动态树(wi)论文Q搞懂了一些;<br />2012q??0日,开始写动态树(wi)Q用的题是QTREEQ花了整整一天时间ȝ写完Q交上去QTLE……<br />2012q??1日,又调了一天,Ҏ(gu)?00+l随机数据都瞬间Q交上去Q还是TLE……<br />2012q??日,W(xu)C2012Qfanhq666讲动态树(wi)Q又搞懂了一点,于是当天晚上回房间以后就开始l调Q交上去QTLE……<br />2012q??日,晚上l箋调QTREEQTLE……<br />在挑战动态树(wi)Nơ失败之后,本沙茶昨天再ơ去挑战动态树(wi)……q次换了一个题Q?a title="BZOJ2002" >BZOJ2002</a>Q传说中的动态树(wi)模板题)<br />一开始还是TLE了,不过后来把数据搞到手以后Q发现TLE的原因ƈ不是常数大,而是d@环了Q最后,l过2h+的调试,ȝ扑ֈ了错误(有好几处Q,l于AC?#8230;…<br /><br />【关于BZOJ2002?br />从每个点i往(i+Ki)q一条边Q如?i+Ki)不存在则往一个附加的l点Q本沙茶的代码中?L(fng)Q因?L(fng)是不能用的Q连一条边Q这样就是一|(wi)Q除1L(fng)外,每个Ҏ(gu)且只有一个后l?#8230;…Q,然后Q问题中的两U操作就?#8220;Ҏ(gu)”?#8220;询问到根的距?#8221;Q可以用动态树(wi)搞;<br /><br />【代码?br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><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; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> MAXN </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">200004</span><span style="color: #000000; ">, INF </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">~</span><span style="color: #000000; ">0U</span><span style="color: #000000; "> </span><span style="color: #000000; ">>></span><span style="color: #000000; "> </span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br /></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; "> node {<br />    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> c[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">], p, sz;<br />    </span><span style="color: #0000FF; ">bool</span><span style="color: #000000; "> rf, d;<br />} T[MAXN];<br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> n;<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> sc(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> _p, </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> _c, </span><span style="color: #0000FF; ">bool</span><span style="color: #000000; "> _d)<br />{<br />    T[_p].c[_d] </span><span style="color: #000000; ">=</span><span style="color: #000000; "> _c; T[_c].p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> _p; T[_c].d </span><span style="color: #000000; ">=</span><span style="color: #000000; "> _d;<br />}<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> upd(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> No)<br />{<br />    T[No].sz </span><span style="color: #000000; ">=</span><span style="color: #000000; "> T[T[No].c[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]].sz </span><span style="color: #000000; ">+</span><span style="color: #000000; "> T[T[No].c[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]].sz </span><span style="color: #000000; ">+</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />}<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> rot(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> No)<br />{<br />    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> T[No].p; </span><span style="color: #0000FF; ">bool</span><span style="color: #000000; "> d </span><span style="color: #000000; ">=</span><span style="color: #000000; "> T[No].d;<br />    </span><span style="color: #0000FF; ">if</span><span style="color: #000000; "> (T[p].rf) {T[p].rf </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">; T[No].rf </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">; T[No].p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> T[p].p;} </span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> sc(T[p].p, No, T[p].d);<br />    sc(p, T[No].c[</span><span style="color: #000000; ">!</span><span style="color: #000000; ">d], d); sc(No, p, </span><span style="color: #000000; ">!</span><span style="color: #000000; ">d); upd(p);<br />}<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> splay(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> No)<br />{<br />    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> p; </span><span style="color: #0000FF; ">while</span><span style="color: #000000; "> (</span><span style="color: #000000; ">!</span><span style="color: #000000; ">T[No].rf) </span><span style="color: #0000FF; ">if</span><span style="color: #000000; "> (T[p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> T[No].p].rf) rot(No); </span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">if</span><span style="color: #000000; "> (T[No].d </span><span style="color: #000000; ">==</span><span style="color: #000000; "> T[p].d) {rot(p); rot(No);} </span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> {rot(No); rot(No);} upd(No);<br />}<br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> access(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> x)<br />{<br />    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> tmp </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />    </span><span style="color: #0000FF; ">do</span><span style="color: #000000; "> {<br />        splay(x); T[T[x].c[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]].rf </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">; T[tmp].rf </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">; sc(x, tmp, </span><span style="color: #000000; ">1</span><span style="color: #000000; ">); upd(x); tmp </span><span style="color: #000000; ">=</span><span style="color: #000000; "> x; x </span><span style="color: #000000; ">=</span><span style="color: #000000; "> T[x].p;<br />    } </span><span style="color: #0000FF; ">while</span><span style="color: #000000; "> (x);<br />}<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> cut(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> x)<br />{<br />    access(x); splay(x); T[T[x].c[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]].rf </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">; T[T[x].c[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]].p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">; sc(x, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">, </span><span style="color: #000000; ">0</span><span style="color: #000000; ">); upd(x);<br />}<br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; "> join(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> x, </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> p)<br />{<br />    access(x); T[x].p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> p;<br />}<br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> main()<br />{<br />    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> m, x, y, z;<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; ">n); n</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br />    re3(i, </span><span style="color: #000000; ">2</span><span style="color: #000000; ">, n) {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); T[i].sz </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">; T[i].rf </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; ">if</span><span style="color: #000000; "> (i </span><span style="color: #000000; ">+</span><span style="color: #000000; "> x </span><span style="color: #000000; "><=</span><span style="color: #000000; "> n) T[i].p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> i </span><span style="color: #000000; ">+</span><span style="color: #000000; "> x; </span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> T[i].p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">;}<br />    T[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">].sz </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">; T[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">].rf </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">; T[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">].sz </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<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);<br />    re(i, m) {<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; ">x);<br />        </span><span style="color: #0000FF; ">if</span><span style="color: #000000; "> (x </span><span style="color: #000000; ">==</span><span style="color: #000000; "> </span><span style="color: #000000; ">1</span><span style="color: #000000; ">) {<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; ">y); y </span><span style="color: #000000; ">+=</span><span style="color: #000000; "> </span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />            access(y); splay(y); printf(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%d\n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, T[T[y].c[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]].sz);<br />        } </span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> {<br />            scanf(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">%d%d</span><span style="color: #000000; ">"</span><span style="color: #000000; ">, </span><span style="color: #000000; ">&</span><span style="color: #000000; ">y, </span><span style="color: #000000; ">&</span><span style="color: #000000; ">z); y </span><span style="color: #000000; ">+=</span><span style="color: #000000; "> </span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />            cut(y); </span><span style="color: #0000FF; ">if</span><span style="color: #000000; "> (y </span><span style="color: #000000; ">+</span><span style="color: #000000; "> z </span><span style="color: #000000; "><=</span><span style="color: #000000; "> n) join(y, y </span><span style="color: #000000; ">+</span><span style="color: #000000; "> z); </span><span style="color: #0000FF; ">else</span><span style="color: #000000; "> join(y, </span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />        }<br />    }<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><br />【易늂?br />Q?Q注意一个点的父l点p有两U可能:(x)如果该结Ҏ(gu)某棵伸展?wi)的根结点则p为它通过轻边q向的另一展树(wi)中的某一个点的编P在原?wi)中Q就是该l点所在展树(wi)代表的链的最上层的那个节点的父结点)Q否则ؓ(f)该结点在伸展?wi)中的父l点~号Q通过重边相连Q;<br />Q?Q在Ҏ(gu)时删除边的时候,如果删除的是轻边则直接把父结点设?卛_Q如果是重边则要sc一下再父l点设ؓ(f)0Q?br />Q?Qrot里面有一个地方很关键Q极易疵Q就是如果p是展树(wi)的根l点Q则除了No的rf改ؓ(f)1Qp的rf改ؓ(f)0之外Q还要把No的父l点设ؓ(f)p的父l点Q?br />Q?Q本题中不涉?qing)整大树(wi)的根(是rootQ,如果需要rootQ则rot中还要加一句:(x)if (root == p) root = No;<br />Q?Qcut里面有一U简便写法(不需要找到x的父l点的)Q先access(x)Q将x伸展到根之后Qx?qing)其叛_?wi)就是原树(wi)中以x为根的子?wi),左子树(wi)就是其它部分,所以直接将x与其左子l点断开卛_Q注意断开的是重边所以要sc一下,再将x的左子结点的父结点设?、rf设ؓ(f)1Q再upd一下)Q?br />Q?Q一定要搞清楚rf的变化(该改时一定要改!Q?br /><br />最后,放上fanhq666大神的ȝQ?br /><a title="0" >0</a><a title="1" >1</a><img src ="http://m.shnenglu.com/MatoNo1/aggbug/166547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-02-26 13:03 <a href="http://m.shnenglu.com/MatoNo1/archive/2012/02/26/166547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>新型LCA法?qing)?wi)的\径剖分模板ȝhttp://m.shnenglu.com/MatoNo1/archive/2012/01/14/164163.htmlMato_No1Mato_No1Sat, 14 Jan 2012 04:34:00 GMThttp://m.shnenglu.com/MatoNo1/archive/2012/01/14/164163.htmlhttp://m.shnenglu.com/MatoNo1/comments/164163.htmlhttp://m.shnenglu.com/MatoNo1/archive/2012/01/14/164163.html#Feedback1http://m.shnenglu.com/MatoNo1/comments/commentRss/164163.htmlhttp://m.shnenglu.com/MatoNo1/services/trackbacks/164163.htmlq种法可以在仅使用?wi)的路径剖分预处理中求出的DEP和UP来求L两点的LCAQ时间复杂度为O(log2N)Q不需要单独的预处理?br />步骤Q假设求a0、b0两点的LCAQ:(x)
Q?Q若UP[a0]==UP[b0]Q则a0、b0位于同一条重链上Q显然a0、b0中深度小的那个就是LCA了,q回l果Q结束;
Q?Q若UP[a0]!=UP[b0]且DEP[UP[a0]]>=DEP[UP[b0]]Q则LCA不可能在a0所在的那条重链?/strong>。证明:(x)若LCA在a0所在的重链上,则UP[a0]必然也是a0、b0的公q先,也就是UP[a0]是b0的祖先。由于UP[a0]的深度大于等于UP[b0]Q若DEP[UP[a0]]>DEP[b0]Q则UP[a0]昄不可能是b0的祖先,否则Q在b0所在的重链上必然存在一个点CQ满DEP[C]=DEP[UP[a0]]Q显ӞC也是b0的祖先,q就说明在树(wi)中同一深度处存在两个不同的l点Q它们都是b0的祖先,q是不可能的Q所以,LCA不可能在a0所在重链上。那么,a0可以上溯到UP[a0]的父l点处(也就是E[FA[UP[a0]]].aQ,b0不动Q然后l判断;
Q?Q若UP[a0]!=UP[b0]且DEP[UP[a0]]<DEP[UP[b0]]Q则LCA不可能在b0所在的重链上,b0上溯到E[FA[UP[b0]]].aQa0不动Ql判断?br />׃a0、b0最多上溯O(log2N)ơ,所以该法一定能在O(log2N)旉内求出LCA(a0, b0)?br />该算法的应用很广Q不光可以在?wi)的路径剖分中快速求出LCAQ精代码Q同时也减少了一些时_(d)因ؓ(f)它不需要像RMQ那样q行预处理)Q而且Q在一般的求LCA问题中,也可以先剖分求出UP再求LCA?br />代码Q?
int LCA(int a, int b)
{
    
while (1) {
        
if (UP[a] == UP[b]) return DEP[a] <= DEP[b] ? a : b;
        
else if (DEP[UP[a]] >= DEP[UP[b]]) a = E[FA[UP[a]]].a; else b = E[FA[UP[b]]].a;
    }
}

?】树(wi)的\径剖分模板ȝQ?br />Q?Q预处理部分Q由于采用新型LCA法Q注意,求LCA的过E写成专门的函数Q,所以,原来预处理部分的?步都不需要了Q也是只要?步:(x)W一步徏有根?wi)求出FA、DEPQ第二步求出SZ划分轻重边;W三步找重链建线D|(wi)求出UP、ord、tot和root。那些ؓ(f)了求RMQ而设|的数组也不需要了?br />Q?Q操作部分:(x)隄在于上溯q程和衔接。设待操作的路径为a0->b0Q注意是有向的,无向的也可以当成有向的处理)QLCA0=LCA(a0, b0)Q?/span>
对于Ҏ(gu)型的?wi)?strong>a0->LCA0
的过E需要包?/span>LCA0Q?/span>b0->LCA0的过E不能包?/span>LCA0。因此当b0==LCA0ӞW二步应该什么事都不做,所以要特判Q此外,如果N==1Q树(wi)中只有一个结点)Qؓ(f)了防止引用根的父l点Q也需要直接特判掉Q所以,上溯q程可以分以?步:(x)
<1>特判Q若n=1Q此时必然有a0==b0==0Q,直接操作0L(fng)点,l束Q?br /><2>(a0->LCA)若a0是父Ҏ(gu)轻边的叶l点Q则单独处理a0Q最新点设ؓ(f)a0Qa0跛_a0的父l点处开始,否则从a0开始(上溯Q。上溯终止条件ؓ(f)DEP[a0]<DEP[LCA0]或者上溯到根结点,每次处理Ӟ设c=”UP[a0]不超LCA?UP[a0]:LCA"Q对[c, a0]D处理(l0=ord[c], r0=ord[a0]Q,再将a0上溯到c的父l点处(若c是根l点则退出)Q处理时Q线D|(wi)中记录的所有有向的Q从左到右的Q信息都要反向;衔接时应不断向右衔接Q?br /><3>(b0->LCA)?lt;2>cMQ两个不同点Q一是有向的信息不要反向Q衔接时应不断向左衔接;二是若c==LCAQ则l0=ord[c]+1Q?br /><4>最后将<2>中和<3>中得到的两个衔接铑ֆ衔接一下即可;

对于Ҏ(gu)型的?wi),a0->LCA0的过E和b0->LCA0的过E都要包含LCA0引出的边Qb0==LCA0以及(qing)N==1时不需要特判(因ؓ(f)它们?x)自动地什么事都不做)Q在处理q程中,l0=ord[c], r0=ord[a0]-1Q要分轻边和重链分别处理Q每ơa0上溯到c而不是c的父l点处;l止条g为DEP[a0]<=DEP[LCA0]?br />
模板题:(x)PKU2831Q动态最生成树(wi)问题Q需要涉?qing)到最生成树(wi)中两点之间\径上的最大边权,用树(wi)的\径剖分。其实本题有ȝ法Q不需要树(wi)的\径剖分)
#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--)
const int MAXN = 1001, MAXM = 100001, INF = ~0U >> 2;
struct _edge {
    
int a, b, w;
} _E[MAXM], _E2[MAXM];
struct edge {
    
int a, b, w, pre, next;
    
bool Z;
} E0[MAXN 
<< 2], E[MAXN << 2];
struct node {
    
int maxw, lch, rch;
} T[MAXN 
<< 2];
int n, _m, m0, m, N, u[MAXN], Q[MAXN], FA[MAXN], DEP[MAXN], SZ[MAXN], UP[MAXN], ord[MAXN], w0[MAXN], tot[MAXN], root[MAXN], l0, r0, x0, res;
bool vst[MAXN];
void init_d()
{
    re(i, n) E0[i].pre 
= E[i].pre = E0[i].next = E[i].next = i;
    m0 
= m = n;
}
void add_edge0(int a, int b, int w)
{
    E0[m0].a 
= a; E0[m0].b = b; E0[m0].w = w; 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].w = w; 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, int w)
{
    E[m].a 
= a; E[m].b = b; E[m].w = w; E[m].Z = 0; E[m].pre = E[a].pre; E[m].next = a; E[a].pre = m; E[E[m].pre].next = m++;
}
int cmp(const void *s1, const void *s2)
{
    
return ((_edge *)s1)->- ((_edge *)s2)->w;
}
int UFS_find(int x)
{
    
int r = x, tmp; while (u[r] >= 0) r = u[r]; while (u[x] >= 0) {tmp = u[x]; u[x] = r; x = tmp;} return r;
}
void UFS_union(int x1, int x2)
{
    
if (u[x1] >= u[x2]) {u[x2] += u[x1]; u[x1] = x2;} else {u[x1] += u[x2]; u[x2] = x1;}
}
int mkt(int l, int r)
{
    
int No = ++N;
    
if (l == r) {T[No].maxw = w0[l]; T[No].lch = T[No].rch = 0;} else {
        
int mid = l + r >> 1, l_r = mkt(l, mid), r_r = mkt(mid + 1, r);
        T[No].maxw 
= T[T[No].lch = l_r].maxw >= T[T[No].rch = r_r].maxw ? T[l_r].maxw : T[r_r].maxw;
    }
    
return No;
}
void prepare()
{
    qsort(_E2, _m, 
sizeof(_E2[0]), cmp);
    re(i, n) u[i] 
= -1;
    
int a, b, r1, r2, total = 0, maxsz, x, n0;
    re(i, _m) {
        a 
= _E2[i].a; b = _E2[i].b; r1 = UFS_find(a); r2 = UFS_find(b);
        
if (r1 != r2) {UFS_union(r1, r2); add_edge0(a, b, _E2[i].w); if (++total == n - 1break;}
    }
    re(i, n) vst[i] 
= 0; Q[0= DEP[0= N = 0; vst[0= 1; FA[0= -1;
    
for (int front=0, rear=0; front<=rear; front++) {
        a 
= Q[front];
        
for (int p=E0[a].next; p != a; p=E0[p].next) {
            b 
= E0[p].b;
            
if (!vst[b]) {FA[b] = m; DEP[b] = DEP[a] + 1; vst[b] = 1; Q[++rear] = b; add_edge(a, b, E0[p].w);}
        }
    }
    rre(i, n) {
        a 
= Q[i]; SZ[a] = 1; maxsz = 0;
        
for (int p=E[a].next; p != a; p=E[p].next) {
            b 
= E[p].b; SZ[a] += SZ[b]; if (SZ[b] > maxsz) {maxsz = SZ[b]; x = p;}
        }
        
if (SZ[a] > 1) E[x].Z = 1;
    }
    UP[
0= ord[0= 0;
    re2(i, 
1, n) {
        a 
= Q[i]; int p = FA[a]; if (E[p].Z) {UP[a] = UP[E[p].a]; ord[a] = ord[E[p].a] + 1;} else {UP[a] = a; ord[a] = 0;}
        
if (SZ[a] == 1 && E[FA[a]].Z) {
            b 
= UP[a]; n0 = ord[a]; for (int j=a; j!=b; j=E[FA[j]].a) w0[--n0] = E[FA[j]].w;
            tot[b] 
= ord[a]; root[b] = mkt(0, ord[a] - 1);
            
for (int j=a; j!=b; j=E[FA[j]].a) {tot[j] = tot[b]; root[j] = root[b];}
        }
    }
}
int LCA(int a, int b)
{
    
while (1) {
        
if (UP[a] == UP[b]) return DEP[a] <= DEP[b] ? a : b;
        
else if (DEP[UP[a]] >= DEP[UP[b]]) a = E[FA[UP[a]]].a; else b = E[FA[UP[b]]].a;
    }
}
void opr0(int l, int r, int No)
{
    
if (l >= l0 && r <= r0) {if (T[No].maxw > res) res = T[No].maxw;} else {
        
int mid = l + r >> 1;
        
if (mid >= l0) opr0(l, mid, T[No].lch);
        
if (mid < r0) opr0(mid + 1, r, T[No].rch);
    }
}
int main()
{
    
int P, s, a0, b0, w0, LCA0, c;
    scanf(
"%d%d%d"&n, &_m, &P); init_d();
    re(i, _m) {
        scanf(
"%d%d%d"&a0, &b0, &w0);
        _E[i].a 
= _E2[i].a = --a0; _E[i].b = _E2[i].b = --b0; _E[i].w = _E2[i].w = w0;
    }
    prepare();
    re(i, P) {
        scanf(
"%d%d"&s, &w0); a0 = _E[--s].a; b0 = _E[s].b; LCA0 = LCA(a0, b0);
        res 
= -INF;
        
while (DEP[a0] > DEP[LCA0]) {
            
if (E[FA[a0]].Z) {
                
if (DEP[UP[a0]] >= DEP[LCA0]) c = UP[a0]; else c = LCA0;
                l0 
= ord[c]; r0 = ord[a0] - 1; opr0(0, tot[a0] - 1, root[a0]); a0 = c;
            } 
else {
                
if (E[FA[a0]].w > res) res = E[FA[a0]].w;
                a0 
= E[FA[a0]].a;
            }
        }
        
while (DEP[b0] > DEP[LCA0]) {
            
if (E[FA[b0]].Z) {
                
if (DEP[UP[b0]] >= DEP[LCA0]) c = UP[b0]; else c = LCA0;
                l0 
= ord[c]; r0 = ord[b0] - 1; opr0(0, tot[b0] - 1, root[b0]); b0 = c;
            } 
else {
                
if (E[FA[b0]].w > res) res = E[FA[b0]].w;
                b0 
= E[FA[b0]].a;
            }
        }
        puts(res 
>= w0 ? "Yes" : "No");
    }
    
return 0;
}

好了Q对于模板也到此ؓ(f)止了Q接下来该搞应用了?img src ="http://m.shnenglu.com/MatoNo1/aggbug/164163.html" width = "1" height = "1" />

Mato_No1 2012-01-14 12:34 发表评论
]]>
【树(wi)的\径剖分】点权型的处理办法、\径的衔接以及(qing)一些细节问?/title><link>http://m.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Thu, 12 Jan 2012 12:44:00 GMT</pubDate><guid>http://m.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html</guid><wfw:comment>http://m.shnenglu.com/MatoNo1/comments/164076.html</wfw:comment><comments>http://m.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/MatoNo1/comments/commentRss/164076.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/MatoNo1/services/trackbacks/164076.html</trackback:ping><description><![CDATA[     摘要: 【例题】[SDOI2011]染色Q注Q数据范围木有交代,应ؓ(f)Q点数N<=105Q操作数M<=105Q所有的颜色C为整C在[0, 109]之间。一、树(wi)的\径剖分当中点权型Q点上有权D边上木有)的处理办法:(x)Q?Q找重链建线D|(wi)的时候,w0中存储tot+1个数Qؓ(f)该重链自上而下的各点的权|例题中ؓ(f)颜色Q;Q?Q除了父Ҏ(gu)轻边的叶l点之外Q树(wi)中的每个l点都属于且仅属于一条重链(Ҏ(gu)定义?..  <a href='http://m.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html'>阅读全文</a><img src ="http://m.shnenglu.com/MatoNo1/aggbug/164076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-01-12 20:44 <a href="http://m.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QTREE——树(wi)的\径剖分(又称?wi)链剖分Q?/title><link>http://m.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Tue, 03 Jan 2012 08:41:00 GMT</pubDate><guid>http://m.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html</guid><wfw:comment>http://m.shnenglu.com/MatoNo1/comments/163491.html</wfw:comment><comments>http://m.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://m.shnenglu.com/MatoNo1/comments/commentRss/163491.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/MatoNo1/services/trackbacks/163491.html</trackback:ping><description><![CDATA[     摘要: 原题地址【有x(wi)的\径剖分的东东在网上介l的太多?#8230;…】常见的路径剖分的方法是轻重边剖分,x?wi)中的边分?f)轻重两部分,Ҏ(gu)Q设SZ[i]Zi为根的子?wi)的大小Q结Ҏ(gu)LQ,则若点x不是叶结点,则其子结点中SZ值最大的Q注意,有多个SZ值最大的子结点应任选一个,只能选一个,防止出现重链怺Q引发歧义)点yQ边(x, y)UCؓ(f)重边Q其余的辚w是轻辏V首q的重边UCؓ(f)重链Q注?..  <a href='http://m.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html'>阅读全文</a><img src ="http://m.shnenglu.com/MatoNo1/aggbug/163491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-01-03 16:41 <a href="http://m.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Splay Tree处理区间问题的几道好题及(qing)ȝhttp://m.shnenglu.com/MatoNo1/archive/2011/06/25/149425.htmlMato_No1Mato_No1Sat, 25 Jun 2011 03:21:00 GMThttp://m.shnenglu.com/MatoNo1/archive/2011/06/25/149425.htmlhttp://m.shnenglu.com/MatoNo1/comments/149425.htmlhttp://m.shnenglu.com/MatoNo1/archive/2011/06/25/149425.html#Feedback2http://m.shnenglu.com/MatoNo1/comments/commentRss/149425.htmlhttp://m.shnenglu.com/MatoNo1/services/trackbacks/149425.htmlQ?QRobotic SortQ?a title="HDU1890" >HDU1890?a title="ZJU2985" >ZJU2985Q?br />本题主要考察的是Ҏ(gu)c问题,序列中给定值的索引问题?br />当Splay Tree用来处理一个序列的时候,其关键字是序列中元素的下标Q而不是元素的倹{这P如果要查扑ֺ列中l定的值的位置Q假讑ֺ列中L两个元素的g相等Q看h无法实现。其实也是有办法实现的:(x)因ؓ(f)元素在树(wi)中的下标是永q不变的Q也是Q设q个序列为AQ如果A[i]在插入Splay Tree时的下标为jQ那么在A[i]被删除之前,其下标一直是jQ永q不?x)变Q注意元素在序列中的下标和在?wi)中的下标是不同的)。利用这一性质可以解决l定值的索引问题?br />对于本题Q每ơ将从序列中Wi的元素到序列中Wi个元素(q里假定元素下标是从1开始的Q而不是从0开始)之间的所有元素反转,q输出第i的元素在反转之前的在序列中的下标。设B[i]为第i的数的初始位置QS[i]?span style="color: #ff0000">初始位置在第i位的元素的下标,B[i]和S[i]都可以通过预处理得到。然后,每次交换前,求出S[B[i]]在树(wi)中的排名Q基本操作)Q再?Q因为有边界l点Q就是该元素目前的位|,而序列中Wi个元素就是树(wi)中第(i+1)的元素Q再执行交换卛_?br />不过需要千万注意的是本题的标记问题Q在求S[B[i]]在树(wi)中的排名Ӟ有可能其先l点上有标记Q需要先遍历其所有的先l点Q再逆向下放标记Q标记只能自向下传Q。另外在交换的时候需要求出S[B[i]]的后l,在求后的过E中需要查找,此时千万别忘了下放标讎ͼȝ_(d)凡是有查扄地方Q就有dmQ?br />代码Q本沙茶太弱了,是抄别h的,因此其算法和上面ȝ的可能有差别Q神犇不要鄙视)
Q?QSuperMemoQ?a title="PKU3580" >PKU3580Q?br />本题?个操作中Qadd、reverse、insert、delete、min都不难搞Q而revolve操作需要涉?qing)到区间交换?br />可以发现Q所谓的旋{其实是交换两个盔R区间Q这对于功能极强的Splay Tree来说Ҏ(gu)不难搞?br />设这两个盔R区间为[x, y]与[y+1, z]Q假讑֮们均非空Q也是x<=y<zQ因其中臛_有一个区间是I区_(d)则交换没有意义)Q先扑ֈ?wi)中x的前P与z的后lSQ这里x、z{指的都是对应的l点Q下同)Q将P伸展到根、将S伸展到根的右子结点处Q则S的左子树(wi)pC区间[x, z]。然后,设S的左子树(wi)的根l点Q也是S的左子结点)为NQ在q棵子树(wi)中找到第1的l点P0与第(y-x+2)的l点S0Q这需要涉?qing)到扑֭树(wi)内WK的操作Q只要把找整|(wi)WK的操作的root改ؓ(f)N卛_Q,它们分别表示x?y+1)Q这样将P0伸展到N处,S0伸展到N的右子结点处Q显然P0无左子树(wi)QS0的左子树(wi)T1表示区间[x+1, y]QS0的右子树(wi)T2表示区间[y+2, z]。然后,先将S0从P0的右子结点移动到P0的左子结点,再将T1作ؓ(f)P0的右子树(wi)Q注意移动是两步Q插入和删除Q。这h子?wi)的中序遍历l果变成了S0->T2->P0->T1Q也是[y+1, z]∪[x, y]?br />另外本题的标记有炚w搞,只需注意rev是逆向标记Q以?qing)查找与dm共存p了?br />代码
Q?QPlay with Chain(HDU3487)
q个cx马好说的,里面的操作在SuperMemo里都有;
代码
Q?Q?a title="AHOI2006 文本~辑?editor)" >AHOI2006 文本~辑?editor)
q题在这一c题里面水的。对于光标,只要用一个值来l护p了?br />另外注意本题极ؓ(f)猥琐?点(题目中米有说明)Q一是最初的文本q不是空的,而是有一个空|二是执行GET操作时光标可能位于文本末,此时应输出空|
代码
Q?QHFTSC2011 高精度计器(apc)Q题目见q个帖子Q?br />q题反映Z一个很囧的问题Q有些信息会(x)被rev整体破坏?br />本题中的操作都是常见操作Q但是本题所需要维护的信息却不是那么容易维护。本题要求维护一子?wi)中所有结Ҏ(gu)表示的元素序列(中序遍历l果Q模一个指定的M的倹{设F[i]为R^i mod M的|q里R是进Ӟ也就是题目中的KQ,则有Q?br />T[x].mod = (T[T[x].c[0]].mod * F[T[T[x].c[1]].sz + 1] + T[x].v * F[T[T[x].c[1]].sz] + T[T[x].c[1]].mod) % M;
q个式子其实是很好理解的?br />关键是,本题的猥琐之处ƈ不在此。注意本题的rev操作Q它?x)整体改变?wi)中所有结Ҏ(gu)记录的mod|q时Q如果再用上面这个式子来l护T[x].modQ就?x)出错,因?f)此时引用到的T[T[x].c[0]].mod和T[T[x].c[1]].mod都是q时的。解册一问题只有一U方法:(x)记录“逆mod”(rmod)Q意思是整个元素序列反转后的modQ即Q?br />T[x].rmod = (T[T[x].c[1]].rmod * F[T[T[x].c[0]].sz + 1] + T[x].v * F[T[T[x].c[0]].sz] + T[T[x].c[0]].rmod) % M;
q样Q在反{某序列的时候,直接根l点的mod值和rmodg换就行了?br />像modq样?x)被反{操作整体破坏的信息还有很多,比如NOI2005 sequence里面的lmax和rmax。如果真的遇到这cM息,只有采用上面的方法?br />另外Q本题第6??0个点有误?br />代码

现在Splay Tree差不多弄完了Q接下来q有N多知名的、不知名的高U数据结?#8230;…旉MS有些不够用了?#8230;…


Mato_No1 2011-06-25 11:21 发表评论
]]>
【NOI2005 l护数列(sequence)】Splay Tree处理序列问题http://m.shnenglu.com/MatoNo1/archive/2011/06/21/149121.htmlMato_No1Mato_No1Tue, 21 Jun 2011 08:06:00 GMThttp://m.shnenglu.com/MatoNo1/archive/2011/06/21/149121.htmlhttp://m.shnenglu.com/MatoNo1/comments/149121.htmlhttp://m.shnenglu.com/MatoNo1/archive/2011/06/21/149121.html#Feedback0http://m.shnenglu.com/MatoNo1/comments/commentRss/149121.htmlhttp://m.shnenglu.com/MatoNo1/services/trackbacks/149121.html【原题见q里?br />本题是Splay Tree处理序列问题Q也是当线D|(wi)用)的一个典型例题?br />
Splay Tree之所以可以当U段?wi)用Q是因ؓ(f)它可以支持一个序列,然后?#8220;左端前趋伸展到根Q右端后l展到根的叛_l点Q取根的叛_l点的左子结?#8221;q种伸展Ҏ(gu)Q对一个序列中的一整段q行整体操作。由于要防止出现前趋或后l不存在的情况,需要在q个序列的两端加入两个边界结点,要求其g能媄响到l点各种记蝲信息的维护(多取0?#8734;?∞Q。这两个边界l点在树(wi)中永q存在,不会(x)被删除?br />
Q?Q结点的引用Q?br />在当U段?wi)用的Splay Tree中,真正的关键字是下标而不是|因此Q?#8220;序列中第i个结?#8221;实际上对应的?#8220;?wi)中W?i+1)的l点”Q因为左边还有一个边界结点)Q这p明在对结点引用时需要找WK的操作。因此,下面?#8220;l点x”指的?#8220;?wi)中W?x+1)的l点”?br />Q?Q标讎ͼ(x)
在线D|(wi)中,如果对一个结Ҏ(gu)表示的线D|体进行了某种操作Q需要在q个l点上打上一个标讎ͼ在下一ơ再扑ֈq个l点Ӟ其标记就?x)下攑ֈ其两个子l点上。在Splay Tree中也可以引入标记。比如要对[2, 6]q一D进行整体操作,将l点1伸展到根的位|,结?伸展到根的右子树(wi)的位|,然后l点7的左子树(wi)pC[2, 6]q一D,对这子?wi)的根结?gu)上标记ƈ立即生效Q必L立即生效Q而不是等下一ơ引用再生效Q,也就是立x变该l点记录的一些信息的倹{如果下ơ再ơ引用到q个l点Q就要将其标C攑ֈ其两个子l点处;
需要注意的一Ҏ(gu)Q如果要伸展某个l点x到r的子l点的位|,必M证从x原来的位|到r的这个子l点Qx伸展后的位置Q上的所有结点上均没有标讎ͼ否则׃(x)D标记混ؕ。因此,必须首先扑ֈq个l点xQ在此过E中不断下放标记?br />Q?Q自底向上维护的信息Q?br />标记可以看成一U自向下维护的信息。除了标C外,作ؓ(f)“U段?#8221;Q往往q要l护一些自底向上维护的信息。比如在sequenceq题中,有lmaxQ左D连l最大和Q、rmaxQ右D连l最大和Q、midmaxQ全D连l最大和Q以?qing)sumQ全D|dQ等信息要维护。对于这cM东其实也很好办,因ؓ(f)子树(wi)大小Qsz域)是一U自底向上维护的信息Q因此对于这些信息只要按照维护sz域的办法l护卛_Q统一写在upd函数里)。唯一的不同点是打标记时它们的值可能要改变?br />Q?Q对q箋插入的结点徏?wi)?x)
本题的插入不是一个一个插入,而是一下子插入一整段Q因此需要先它们徏成一|(wi)。一般徏?wi)操作都是递归的,q里也一栗设目前要对A[l..r]建树(wi)QA为待插入序列Q,若l>r则退出,否则扑ֈ位于中间的元素mid = l + r >> 1Q将A[mid]作根Q再对A[l..mid-1]建左子树(wi)Q对A[mid+1..r]建右子树(wi)卛_。这样可以保证一开始徏的就是一^衡树(wi)Q减常数因子?br />Q?Q回收空_(d)(x)
Ҏ(gu)本题的数据范围提C,插入的结Ҏ(gu)L最多可能达?000000Q但在Q何时L(wi)中最多只?00002个结点(包括两个边界Q,此时Z节省I间Q可以采用@环队列回收空间的Ҏ(gu)。即Q一开始将所有的可用I间Q可用下标,本题?~500002Q存在@环队列Q里,同时讄头尾指针front和rearQ每ơ如果有新结Ҏ(gu)入,取出Q[front]q作为新l点的下标,如果有结点要删除Q本题是一ơ删除整子?wi),因此在删除后需要分别回收它们的I间Q,则从rear开始,每个删除的l点的下标放回到Q里。当Ӟq种Ҏ(gu)是要牺牲一定的旉的,因此在空间不是特别吃紧的情况下不要用?br />
?012q??6日更新?br />今天重写sequence的时候,U然发现加入的边界点可能?x)对lmax、rmax、midmax{的l护造成影响Q当序列中所有的值都是负数时Q若边界点的D?Q将使这3个g?Q所以,边界点的值应设ؓ(f)-INFQ不?x)媄响到sumQ因为可以单独调出[l, r]的sumQ避开边界Q。这p明ƈ非所有这L(fng)题中都可以设|边界点Q比如HFTSC2011的那题就不行Q,如果边界点会(x)对维护的信息造成影响Q就不能讄边界点,在各个操作中Q分4U情况判断。(代码已经修改Q?br />
下面上代码了Q?
#include <iostream>
#include 
<stdio.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++)
const int MAXN = 500002, NOSM = -2000, INF = ~0U >> 2;
struct node {
    
int v, c[2], p, sz, sum, lmax, rmax, midmax, sm;
    
bool rev, d;
} T[MAXN 
+ 1];
int root, Q[MAXN + 1], front, rear, a[MAXN], len, res;
int max(int SS0, int SS1)
{
    
return SS0 >= SS1 ? SS0 : SS1;
}
int max(int SS0, int SS1, int SS2)
{
    
int M0 = SS0 >= SS1 ? SS0 : SS1; return M0 >= SS2 ? M0 : SS2;
}
void newnode(int n, int _v)
{
    T[n].v 
= T[n].sum = T[n].lmax = T[n].rmax = T[n].midmax = _v; T[n].c[0= T[n].c[1= 0; T[n].sz = 1; T[n].sm = NOSM; T[n].rev = 0;
}
void sc(int _p, int _c, bool _d)
{
    T[_p].c[_d] 
= _c; T[_c].p = _p; T[_c].d = _d;
}
void sm_opr(int x, int SM)
{
    T[x].sum 
= T[x].sz * SM;
    
if (SM > 0) T[x].lmax = T[x].rmax = T[x].midmax = T[x].sum; else T[x].lmax = T[x].rmax = T[x].midmax = SM;
}
void rev_opr(int x)
{
    
int c0 = T[x].c[0], c1 = T[x].c[1]; sc(x, c0, 1); sc(x, c1, 0);
    
int tmp = T[x].lmax; T[x].lmax = T[x].rmax; T[x].rmax = tmp;
}
void dm(int x)
{
    
int SM0 = T[x].sm;
    
if (SM0 != NOSM) {
        T[x].v 
= T[T[x].c[0]].sm = T[T[x].c[1]].sm = SM0; T[x].sm = NOSM;
        sm_opr(T[x].c[
0], SM0); sm_opr(T[x].c[1], SM0);
    }
    
if (T[x].rev) {
        T[T[x].c[
0]].rev = !T[T[x].c[0]].rev; T[T[x].c[1]].rev = !T[T[x].c[1]].rev; T[x].rev = 0;
        rev_opr(T[x].c[
0]); rev_opr(T[x].c[1]);
    }
}
void upd(int x)
{
    
int c0 = T[x].c[0], c1 = T[x].c[1];
    T[x].sz 
= T[c0].sz + T[c1].sz + 1;
    T[x].sum 
= T[c0].sum + T[c1].sum + T[x].v;
    T[x].lmax 
= max(T[c0].lmax, T[c0].sum + T[x].v + max(T[c1].lmax, 0));
    T[x].rmax 
= max(T[c1].rmax, max(T[c0].rmax, 0+ T[x].v + T[c1].sum);
    T[x].midmax 
= max(T[c0].midmax, T[c1].midmax, max(T[c0].rmax, 0+ T[x].v + max(T[c1].lmax, 0));
}
void rot(int x)
{
    
int y = T[x].p; bool d = T[x].d;
    
if (y == root) {root = x; T[root].p = 0;} else sc(T[y].p, x, T[y].d);
    sc(y, T[x].c[
!d], d); sc(x, y, !d); upd(y);
}
void splay(int x, int r)
{
    
int p; while ((p = T[x].p) != r) if (T[p].p == r) rot(x); else if (T[x].d == T[p].d) {rot(p); rot(x);} else {rot(x); rot(x);} upd(x);
}
int Find_Kth(int K)
{
    
int i = root, S0;
    
while (i) {
        dm(i); S0 
= T[T[i].c[0]].sz + 1;
        
if (K == S0) breakelse if (K < S0) i = T[i].c[0]; else {K -= S0; i = T[i].c[1];}
    }
    
return i;
}
int mkt(int l, int r)
{
    
if (l > r) return 0;
    
int n0 = Q[front], mid = l + r >> 1if (front == MAXN) front = 1else front++;
    newnode(n0, a[mid]); 
int l_r = mkt(l, mid - 1), r_r = mkt(mid + 1, r);
    sc(n0, l_r, 
0); sc(n0, r_r, 1); upd(n0); return n0;
}
void ins(int pos)
{
    
int P0 = Find_Kth(pos); splay(P0, 0); int P1 = Find_Kth(pos + 1); splay(P1, root); sc(P1, mkt(0, len - 1), 0); upd(P1); upd(P0);
}
void era(int x)
{
    
if (!x) return;
    
if (rear == MAXN) rear = 1else rear++; Q[rear] = x;
    era(T[x].c[
0]); era(T[x].c[1]);
}
void del(int l, int r)
{
    
int P0 = Find_Kth(l - 1); splay(P0, 0); int P1 = Find_Kth(r + 1); splay(P1, root); 
    
int root0 = T[P1].c[0]; sc(P1, 00); upd(P1); upd(P0); era(root0);
}
void mksame(int l, int r, int x)
{
    
int P0 = Find_Kth(l - 1); splay(P0, 0); int P1 = Find_Kth(r + 1); splay(P1, root); 
    
int n = T[P1].c[0]; T[n].sm = x; sm_opr(n, x); upd(P1); upd(P0);
}
void reve(int l, int r)
{
    
int P0 = Find_Kth(l - 1); splay(P0, 0); int P1 = Find_Kth(r + 1); splay(P1, root); 
    
int n = T[P1].c[0]; T[n].rev = !T[n].rev; rev_opr(n); upd(P1); upd(P0);
}
int get_sum(int l, int r)
{
    
int P0 = Find_Kth(l - 1); splay(P0, 0); int P1 = Find_Kth(r + 1); splay(P1, root); 
    
int n = T[P1].c[0]; return T[n].sum;
}
int max_sum()
{
    
return T[root].midmax;
}
void prepare()
{
    T[
0].sz = T[0].sum = T[0].lmax = T[0].rmax = T[0].midmax = 0;
    front 
= 3; rear = MAXN; re1(i, MAXN) Q[i] = i;
    newnode(
1-INF); newnode(2-INF); sc(121); root = 1; T[root].p = 0;
}
int main()
{
    freopen(
"sequence.in""r", stdin);
    freopen(
"sequence.out""w", stdout);
    prepare();
    
int m, l, r, x;
    scanf(
"%d%d"&len, &m); char ch = getchar(), str[1000];
    re(i, len) scanf(
"%d"&a[i]); ins(1);
    re(i, m) {
        scanf(
"%s", str);
        
if (!strcmp(str, "INSERT")) {scanf("%d%d"&l, &len); re(i, len) scanf("%d"&a[i]); ins(++l);}
        
if (!strcmp(str, "DELETE")) {scanf("%d%d"&l, &r); r += l++; del(l, r);}
        
if (!strcmp(str, "MAKE-SAME")) {scanf("%d%d%d"&l, &r, &x); r += l++; mksame(l, r, x);}
        
if (!strcmp(str, "REVERSE")) {scanf("%d%d"&l, &r); r += l++; reve(l, r);}
        
if (!strcmp(str, "GET-SUM")) {scanf("%d%d"&l, &r); r += l++; printf("%d\n", get_sum(l, r));}
        
if (!strcmp(str, "MAX-SUM")) printf("%d\n", max_sum());
        ch 
= getchar();
    }
    fclose(stdin); fclose(stdout);
    
return 0;
}

最后把我的q个代码与BYVoid犇的本题代码进行测试比较,l果QBYVoid犇的代码见q里Q:(x)

BYVoid犇的:(x)


本沙茶的Q?br />

【相兌文?br />

Mato_No1 2011-06-21 16:06 发表评论
]]>
þǿdŮ| 91þùۺϾƷ | aëƬþ| AëƬþþƷ| þþƷһ| ŷ˾þۺһ| ھƷþþþӰԺ| þþƷۺһ| ޹Ʒþ98| þĻһ| ˾ƷۺϾþþþ| ԴӰȷþԴ| ҹAVëƬþ| ƷŮٸaѾþ| ŷþþþþҹƷ| һһþaþۺϾƷ һһþۺϺݺ | þþþAVרվ| ޡvþþ뾫Ʒ| þù| 91Ʒ91þ| þþ뾫ƷպĦ| þþþۺϹŷһ| Ʒþþþþô| ݺۺϾþAVһ| 㽶97þ| ھƷþù½| þþþþþž99Ʒ| ŮƷþþ2020| ޵һAVվþþƷ˵AV| avþþþþòվ| þAV߳AVAV| þˬˬˬ| ĻþӰԺ| þþþ?V| þۺ϶㼤þ| 97þþƷһ| 69SEXþþƷ鶹| þþƷaĻؿ| ɫ88þþþø߳ۺӰԺ| þþþþaëƬ| 99ŷþþþƷѿ|