??xml version="1.0" encoding="utf-8" standalone="yes"?>久久精品无码一区二区无码 ,亚洲精品乱码久久久久久,精品久久久久久中文字幕人妻最新http://www.shnenglu.com/MatoNo1/archive/2013/08/31/202905.htmlMato_No1Mato_No1Sat, 31 Aug 2013 15:39:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2013/08/31/202905.htmlhttp://www.shnenglu.com/MatoNo1/comments/202905.htmlhttp://www.shnenglu.com/MatoNo1/archive/2013/08/31/202905.html#Feedback1http://www.shnenglu.com/MatoNo1/comments/commentRss/202905.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/202905.html阅读全文

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

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

Mato_No1 2012-11-25 14:54 发表评论
]]>
l于会写动态树?/title><link>http://www.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://www.shnenglu.com/MatoNo1/archive/2012/02/26/166547.html</guid><wfw:comment>http://www.shnenglu.com/MatoNo1/comments/166547.html</wfw:comment><comments>http://www.shnenglu.com/MatoNo1/archive/2012/02/26/166547.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/MatoNo1/comments/commentRss/166547.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/MatoNo1/services/trackbacks/166547.html</trackback:ping><description><![CDATA[【背景?br />2012q??9日,本沙茶开始看动态树论文Q搞懂了一些;<br />2012q??0日,开始写动态树Q用的题是QTREEQ花了整整一天时间ȝ写完Q交上去QTLE……<br />2012q??1日,又调了一天,Ҏ?00+l随机数据都瞬间Q交上去Q还是TLE……<br />2012q??日,WC2012Qfanhq666讲动态树Q又搞懂了一点,于是当天晚上回房间以后就开始l调Q交上去QTLE……<br />2012q??日,晚上l箋调QTREEQTLE……<br />在挑战动态树Nơ失败之后,本沙茶昨天再ơ去挑战动态树……q次换了一个题Q?a title="BZOJ2002" >BZOJ2002</a>Q传说中的动态树模板题)<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本沙茶的代码中?LQ因?L是不能用的Q连一条边Q这样就是一|Q除1L外,每个Ҏ且只有一个后l?#8230;…Q,然后Q问题中的两U操作就?#8220;Ҏ”?#8220;询问到根的距?#8221;Q可以用动态树搞;<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可能:如果该结Ҏ某棵伸展树的根结点则p为它通过轻边q向的另一展树中的某一个点的编P在原树中Q就是该l点所在展树代表的链的最上层的那个节点的父结点)Q否则ؓ该结点在伸展树中的父l点~号Q通过重边相连Q;<br />Q?Q在Ҏ时删除边的时候,如果删除的是轻边则直接把父结点设?卛_Q如果是重边则要sc一下再父l点设ؓ0Q?br />Q?Qrot里面有一个地方很关键Q极易疵Q就是如果p是展树的根l点Q则除了No的rf改ؓ1Qp的rf改ؓ0之外Q还要把No的父l点设ؓp的父l点Q?br />Q?Q本题中不涉及整大树的根(是rootQ,如果需要rootQ则rot中还要加一句:if (root == p) root = No;<br />Q?Qcut里面有一U简便写法(不需要找到x的父l点的)Q先access(x)Q将x伸展到根之后Qx及其叛_树就是原树中以x为根的子树,左子树就是其它部分,所以直接将x与其左子l点断开卛_Q注意断开的是重边所以要sc一下,再将x的左子结点的父结点设?、rf设ؓ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://www.shnenglu.com/MatoNo1/aggbug/166547.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-02-26 13:03 <a href="http://www.shnenglu.com/MatoNo1/archive/2012/02/26/166547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>新型LCA法及树的\径剖分模板ȝhttp://www.shnenglu.com/MatoNo1/archive/2012/01/14/164163.htmlMato_No1Mato_No1Sat, 14 Jan 2012 04:34:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2012/01/14/164163.htmlhttp://www.shnenglu.com/MatoNo1/comments/164163.htmlhttp://www.shnenglu.com/MatoNo1/archive/2012/01/14/164163.html#Feedback1http://www.shnenglu.com/MatoNo1/comments/commentRss/164163.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/164163.htmlq种法可以在仅使用树的路径剖分预处理中求出的DEP和UP来求L两点的LCAQ时间复杂度为O(log2N)Q不需要单独的预处理?br />步骤Q假设求a0、b0两点的LCAQ:
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>。证明:若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就说明在树中同一深度处存在两个不同的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不光可以在树的路径剖分中快速求出LCAQ精代码Q同时也减少了一些时_因ؓ它不需要像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;
    }
}

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

对于Ҏ型的树,a0->LCA0的过E和b0->LCA0的过E都要包含LCA0引出的边Qb0==LCA0以及N==1时不需要特判(因ؓ它们会自动地什么事都不做)Q在处理q程中,l0=ord[c], r0=ord[a0]-1Q要分轻边和重链分别处理Q每ơa0上溯到c而不是c的父l点处;l止条g为DEP[a0]<=DEP[LCA0]?br />
模板题:PKU2831Q动态最生成树问题Q需要涉及到最生成树中两点之间\径上的最大边权,用树的\径剖分。其实本题有ȝ法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--)
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对于模板也到此ؓ止了Q接下来该搞应用了?img src ="http://www.shnenglu.com/MatoNo1/aggbug/164163.html" width = "1" height = "1" />

Mato_No1 2012-01-14 12:34 发表评论
]]>
【树的\径剖分】点权型的处理办法、\径的衔接以及一些细节问?/title><link>http://www.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://www.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html</guid><wfw:comment>http://www.shnenglu.com/MatoNo1/comments/164076.html</wfw:comment><comments>http://www.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/MatoNo1/comments/commentRss/164076.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/MatoNo1/services/trackbacks/164076.html</trackback:ping><description><![CDATA[     摘要: 【例题】[SDOI2011]染色Q注Q数据范围木有交代,应ؓQ点数N<=105Q操作数M<=105Q所有的颜色C为整C在[0, 109]之间。一、树的\径剖分当中点权型Q点上有权D边上木有)的处理办法:Q?Q找重链建线D|的时候,w0中存储tot+1个数Qؓ该重链自上而下的各点的权|例题中ؓ颜色Q;Q?Q除了父Ҏ轻边的叶l点之外Q树中的每个l点都属于且仅属于一条重链(Ҏ定义?..  <a href='http://www.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html'>阅读全文</a><img src ="http://www.shnenglu.com/MatoNo1/aggbug/164076.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-01-12 20:44 <a href="http://www.shnenglu.com/MatoNo1/archive/2012/01/12/164076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QTREE——树的\径剖分(又称树链剖分Q?/title><link>http://www.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://www.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html</guid><wfw:comment>http://www.shnenglu.com/MatoNo1/comments/163491.html</wfw:comment><comments>http://www.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/MatoNo1/comments/commentRss/163491.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/MatoNo1/services/trackbacks/163491.html</trackback:ping><description><![CDATA[     摘要: 原题地址【有x的\径剖分的东东在网上介l的太多?#8230;…】常见的路径剖分的方法是轻重边剖分,x树中的边分ؓ轻重两部分,ҎQ设SZ[i]Zi为根的子树的大小Q结ҎLQ,则若点x不是叶结点,则其子结点中SZ值最大的Q注意,有多个SZ值最大的子结点应任选一个,只能选一个,防止出现重链怺Q引发歧义)点yQ边(x, y)UCؓ重边Q其余的辚w是轻辏V首q的重边UCؓ重链Q注?..  <a href='http://www.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html'>阅读全文</a><img src ="http://www.shnenglu.com/MatoNo1/aggbug/163491.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-01-03 16:41 <a href="http://www.shnenglu.com/MatoNo1/archive/2012/01/03/163491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Splay Tree处理区间问题的几道好题及ȝhttp://www.shnenglu.com/MatoNo1/archive/2011/06/25/149425.htmlMato_No1Mato_No1Sat, 25 Jun 2011 03:21:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2011/06/25/149425.htmlhttp://www.shnenglu.com/MatoNo1/comments/149425.htmlhttp://www.shnenglu.com/MatoNo1/archive/2011/06/25/149425.html#Feedback2http://www.shnenglu.com/MatoNo1/comments/commentRss/149425.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/149425.htmlQ?QRobotic SortQ?a title="HDU1890" >HDU1890?a title="ZJU2985" >ZJU2985Q?br />本题主要考察的是Ҏc问题,序列中给定值的索引问题?br />当Splay Tree用来处理一个序列的时候,其关键字是序列中元素的下标Q而不是元素的倹{这P如果要查扑ֺ列中l定的值的位置Q假讑ֺ列中L两个元素的g相等Q看h无法实现。其实也是有办法实现的:因ؓ元素在树中的下标是永q不变的Q也是Q设q个序列为AQ如果A[i]在插入Splay Tree时的下标为jQ那么在A[i]被删除之前,其下标一直是jQ永q不会变Q注意元素在序列中的下标和在树中的下标是不同的)。利用这一性质可以解决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]]在树中的排名Q基本操作)Q再?Q因为有边界l点Q就是该元素目前的位|,而序列中Wi个元素就是树中第(i+1)的元素Q再执行交换卛_?br />不过需要千万注意的是本题的标记问题Q在求S[B[i]]在树中的排名Ӟ有可能其先l点上有标记Q需要先遍历其所有的先l点Q再逆向下放标记Q标记只能自向下传Q。另外在交换的时候需要求出S[B[i]]的后l,在求后的过E中需要查找,此时千万别忘了下放标讎ͼȝ_凡是有查扄地方Q就有dmQ?br />代码Q本沙茶太弱了,是抄别h的,因此其算法和上面ȝ的可能有差别Q神犇不要鄙视)
Q?QSuperMemoQ?a title="PKU3580" >PKU3580Q?br />本题?个操作中Qadd、reverse、insert、delete、min都不难搞Q而revolve操作需要涉及到区间交换?br />可以发现Q所谓的旋{其实是交换两个盔R区间Q这对于功能极强的Splay Tree来说Ҏ不难搞?br />设这两个盔R区间为[x, y]与[y+1, z]Q假讑֮们均非空Q也是x<=y<zQ因其中臛_有一个区间是I区_则交换没有意义)Q先扑ֈ树中x的前P与z的后lSQ这里x、z{指的都是对应的l点Q下同)Q将P伸展到根、将S伸展到根的右子结点处Q则S的左子树pC区间[x, z]。然后,设S的左子树的根l点Q也是S的左子结点)为NQ在q棵子树中找到第1的l点P0与第(y-x+2)的l点S0Q这需要涉及到扑֭树内WK的操作Q只要把找整|WK的操作的root改ؓN卛_Q,它们分别表示x?y+1)Q这样将P0伸展到N处,S0伸展到N的右子结点处Q显然P0无左子树QS0的左子树T1表示区间[x+1, y]QS0的右子树T2表示区间[y+2, z]。然后,先将S0从P0的右子结点移动到P0的左子结点,再将T1作ؓP0的右子树Q注意移动是两步Q插入和删除Q。这h子树的中序遍历l果变成了S0->T2->P0->T1Q也是[y+1, z]∪[x, y]?br />另外本题的标记有炚w搞,只需注意rev是逆向标记Q以及查找与dm共存p了?br />代码
Q?QPlay with Chain(HDU3487)
q个cx马好说的,里面的操作在SuperMemo里都有;
代码
Q?Q?a title="AHOI2006 文本~辑?editor)" >AHOI2006 文本~辑?editor)
q题在这一c题里面水的。对于光标,只要用一个值来l护p了?br />另外注意本题极ؓ猥琐?点(题目中米有说明)Q一是最初的文本q不是空的,而是有一个空|二是执行GET操作时光标可能位于文本末,此时应输出空|
代码
Q?QHFTSC2011 高精度计器(apc)Q题目见q个帖子Q?br />q题反映Z一个很囧的问题Q有些信息会被rev整体破坏?br />本题中的操作都是常见操作Q但是本题所需要维护的信息却不是那么容易维护。本题要求维护一子树中所有结Ҏ表示的元素序列(中序遍历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它会整体改变树中所有结Ҏ记录的mod|q时Q如果再用上面这个式子来l护T[x].modQ就会出错,因ؓ此时引用到的T[T[x].c[0]].mod和T[T[x].c[1]].mod都是q时的。解册一问题只有一U方法:记录“逆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样会被反{操作整体破坏的信息还有很多,比如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://www.shnenglu.com/MatoNo1/archive/2011/06/21/149121.htmlMato_No1Mato_No1Tue, 21 Jun 2011 08:06:00 GMThttp://www.shnenglu.com/MatoNo1/archive/2011/06/21/149121.htmlhttp://www.shnenglu.com/MatoNo1/comments/149121.htmlhttp://www.shnenglu.com/MatoNo1/archive/2011/06/21/149121.html#Feedback0http://www.shnenglu.com/MatoNo1/comments/commentRss/149121.htmlhttp://www.shnenglu.com/MatoNo1/services/trackbacks/149121.html【原题见q里?br />本题是Splay Tree处理序列问题Q也是当线D|用)的一个典型例题?br />
Splay Tree之所以可以当U段树用Q是因ؓ它可以支持一个序列,然后?#8220;左端前趋伸展到根Q右端后l展到根的叛_l点Q取根的叛_l点的左子结?#8221;q种伸展ҎQ对一个序列中的一整段q行整体操作。由于要防止出现前趋或后l不存在的情况,需要在q个序列的两端加入两个边界结点,要求其g能媄响到l点各种记蝲信息的维护(多取0?#8734;?∞Q。这两个边界l点在树中永q存在,不会被删除?br />
Q?Q结点的引用Q?br />在当U段树用的Splay Tree中,真正的关键字是下标而不是|因此Q?#8220;序列中第i个结?#8221;实际上对应的?#8220;树中W?i+1)的l点”Q因为左边还有一个边界结点)Q这p明在对结点引用时需要找WK的操作。因此,下面?#8220;l点x”指的?#8220;树中W?x+1)的l点”?br />Q?Q标讎ͼ
在线D|中,如果对一个结Ҏ表示的线D|体进行了某种操作Q需要在q个l点上打上一个标讎ͼ在下一ơ再扑ֈq个l点Ӟ其标记就会下攑ֈ其两个子l点上。在Splay Tree中也可以引入标记。比如要对[2, 6]q一D进行整体操作,将l点1伸展到根的位|,结?伸展到根的右子树的位|,然后l点7的左子树pC[2, 6]q一D,对这子树的根结Ҏ上标记ƈ立即生效Q必L立即生效Q而不是等下一ơ引用再生效Q,也就是立x变该l点记录的一些信息的倹{如果下ơ再ơ引用到q个l点Q就要将其标C攑ֈ其两个子l点处;
需要注意的一ҎQ如果要伸展某个l点x到r的子l点的位|,必M证从x原来的位|到r的这个子l点Qx伸展后的位置Q上的所有结点上均没有标讎ͼ否则׃D标记混ؕ。因此,必须首先扑ֈq个l点xQ在此过E中不断下放标记?br />Q?Q自底向上维护的信息Q?br />标记可以看成一U自向下维护的信息。除了标C外,作ؓ“U段?#8221;Q往往q要l护一些自底向上维护的信息。比如在sequenceq题中,有lmaxQ左D连l最大和Q、rmaxQ右D连l最大和Q、midmaxQ全D连l最大和Q以及sumQ全D|dQ等信息要维护。对于这cM东其实也很好办,因ؓ子树大小Qsz域)是一U自底向上维护的信息Q因此对于这些信息只要按照维护sz域的办法l护卛_Q统一写在upd函数里)。唯一的不同点是打标记时它们的值可能要改变?br />Q?Q对q箋插入的结点徏树:
本题的插入不是一个一个插入,而是一下子插入一整段Q因此需要先它们徏成一|。一般徏树操作都是递归的,q里也一栗设目前要对A[l..r]建树QA为待插入序列Q,若l>r则退出,否则扑ֈ位于中间的元素mid = l + r >> 1Q将A[mid]作根Q再对A[l..mid-1]建左子树Q对A[mid+1..r]建右子树卛_。这样可以保证一开始徏的就是一^衡树Q减常数因子?br />Q?Q回收空_
Ҏ本题的数据范围提C,插入的结ҎL最多可能达?000000Q但在Q何时L中最多只?00002个结点(包括两个边界Q,此时Z节省I间Q可以采用@环队列回收空间的Ҏ。即Q一开始将所有的可用I间Q可用下标,本题?~500002Q存在@环队列Q里,同时讄头尾指针front和rearQ每ơ如果有新结Ҏ入,取出Q[front]q作为新l点的下标,如果有结点要删除Q本题是一ơ删除整子树,因此在删除后需要分别回收它们的I间Q,则从rear开始,每个删除的l点的下标放回到Q里。当Ӟq种Ҏ是要牺牲一定的旉的,因此在空间不是特别吃紧的情况下不要用?br />
?012q??6日更新?br />今天重写sequence的时候,U然发现加入的边界点可能会对lmax、rmax、midmax{的l护造成影响Q当序列中所有的值都是负数时Q若边界点的D?Q将使这3个g?Q所以,边界点的值应设ؓ-INFQ不会媄响到sumQ因为可以单独调出[l, r]的sumQ避开边界Q。这p明ƈ非所有这L题中都可以设|边界点Q比如HFTSC2011的那题就不行Q,如果边界点会对维护的信息造成影响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:

BYVoid犇的:


本沙茶的Q?br />

【相兌文?br />

Mato_No1 2011-06-21 16:06 发表评论
]]>
þۺ㽶AV| þþƷһӰ| ˾þô߽| vaĻþ| þ޹vwww| þþоƷĻ| ɫۺϾþҹɫƷ| ŷvaþþþ| ĻhdþþƷ| ޹СƵƷþþ| þþһ| ŷ˾þþƷ| 69þþƷһ| þ¶Ʒ| Ʒþþþþø| ղƷaëƬþ| þþþþþž99Ʒ| ˾þav| ƷVIDEOSSEXþ÷| þþƷAV㽶| þþþƷ| Ҳȥþۺ| ޾Ʒþþþþ| þۺ¶þü| 99þþžžƷ| պƷþþþþ| ˾ƷþѶ| AþþƷ| þþþþþŮú| þ˳ƷCAOPOREN| Ʒ˾Ʒþþ| ˾þ91| wwwԾþþcom| www.þ| þֻƷ99| þ޹ҹƷƬ| þþƷһ| ƷŮþþþ| ɫݺȷӰþ| 99þwww˳ɾƷ| 99þþžžƷ|