﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-NARUTOACM-随笔分类-知识</title><link>http://www.cppblog.com/NARUTOACM/category/13312.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 05 Apr 2010 19:11:19 GMT</lastBuildDate><pubDate>Mon, 05 Apr 2010 19:11:19 GMT</pubDate><ttl>60</ttl><item><title>关于最短完全覆盖子序列</title><link>http://www.cppblog.com/NARUTOACM/archive/2010/03/25/110555.html</link><dc:creator>NARUTOACM</dc:creator><author>NARUTOACM</author><pubDate>Thu, 25 Mar 2010 14:35:00 GMT</pubDate><guid>http://www.cppblog.com/NARUTOACM/archive/2010/03/25/110555.html</guid><wfw:comment>http://www.cppblog.com/NARUTOACM/comments/110555.html</wfw:comment><comments>http://www.cppblog.com/NARUTOACM/archive/2010/03/25/110555.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/NARUTOACM/comments/commentRss/110555.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/NARUTOACM/services/trackbacks/110555.html</trackback:ping><description><![CDATA[<div style="LAYOUT-GRID:  15.6pt none" class=Section0>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">今天切<font face="Times New Roman">010</font><font face=宋体>大神博客中收录的</font><font face="Times New Roman">KMP</font><font face=宋体>题时，有一道题是关于最短完全覆盖子序列的。题目地址：</font></span><span><a href="http://162.105.81.212/JudgeOnline/problem?id=1961"><span style="FONT-FAMILY: '宋体'; COLOR: rgb(0,0,255); FONT-SIZE: 10pt; TEXT-DECORATION: underline; mso-spacerun: 'yes'" class=15>http://162.105.81.212/JudgeOnline/problem?id=1961</span></a></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">题意就不说了，很容易理解。</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">做该题的时候，我先自己在草稿纸上写了几个有完全覆盖子序列的串，如<font face="Times New Roman">ababab</font><font face=宋体>，用</font><font face="Times New Roman">kmp</font><font face=宋体>求他的</font><font face="Times New Roman">next</font><font face=宋体>值分别是：</font><font face="Times New Roman">0&nbsp;0&nbsp;1&nbsp;2&nbsp;3&nbsp;4</font><font face=宋体>。于是本菜得出结论：如果一个串有完全覆盖子序列的话那么最短的完全覆盖子序列一定满足：如果该子序列长度为</font><font face="Times New Roman">x</font><font face=宋体>，那么</font><font face="Times New Roman">next</font><font face=宋体>值前面必是</font><font face="Times New Roman">x</font><font face=宋体>个</font><font face="Times New Roman">0</font><font face=宋体>，然后依次递增</font><font face="Times New Roman">1</font><font face=宋体>。写代码的时候本菜又突然发现，先设主串长度为</font><font face="Times New Roman">len</font><font face=宋体>，则</font><font face="Times New Roman">len-next[len]</font><font face=宋体>居然等于最短完全覆盖子序列的长度。于是本菜就</font><font face="Times New Roman">yy</font><font face=宋体>了一下，直接判断</font><font face="Times New Roman">len%(len-next[len])</font><font face=宋体>的值是否为</font><font face="Times New Roman">0</font><font face=宋体>。如果为</font><font face="Times New Roman">0</font><font face=宋体>，那么存在，且长度为</font><font face="Times New Roman">len-next[len]</font><font face=宋体>，否则不存在。没想到居然</font><font face="Times New Roman">AC</font><font face=宋体>！！不得不自恋下本菜的</font><font face="Times New Roman">RP</font><font face=宋体>！</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">做完之后本菜百思不得其解，问了下<font face="Times New Roman">010</font><font face=宋体>大神，表示只知道这个道理。于是好奇心有点强的我想自己证明试试。于是就有了如下的见解</font><font face="Times New Roman">(</font><font face=宋体>大牛无需观看</font><font face="Times New Roman">..)</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">先根据<font face="Times New Roman">KMP</font><font face=宋体>算法求串</font><font face="Times New Roman">S</font><font face=宋体>的</font><font face="Times New Roman">next</font><font face=宋体>值，假设串长为</font><font face="Times New Roman">len</font><font face=宋体>，现在猜想如果</font><font face="Times New Roman">len%(len-next[len])==0</font><font face=宋体>时，有完全覆盖子序列，且最短完全覆盖子序列的长度即为</font><font face="Times New Roman">len-next[len]</font><font face=宋体>。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">证明之前先讲述一下什么是完全覆盖子序列。假设串<font face="Times New Roman">S="abcabcabcabc"</font><font face=宋体>，那么我们说</font><font face="Times New Roman">abc</font><font face=宋体>、</font><font face="Times New Roman">abcabc</font><font face=宋体>、</font><font face="Times New Roman">abcabcabcabc</font><font face=宋体>是</font><font face="Times New Roman">S</font><font face=宋体>的完全覆盖子序列。即一个子串能完全的覆盖主串的子序列叫做完全覆盖子序列。所谓最短，即完全覆盖子序列中最短的，例子中的最短完全覆盖子序列是</font><font face="Times New Roman">abc</font><font face=宋体>。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">证明：</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">我们知道当串<font face="Times New Roman">S</font><font face=宋体>有完全覆盖子序列时，那么一定满足上式，即</font><font face="Times New Roman">len%(len-next[len])==0</font><font face=宋体>。因为根据</font><font face="Times New Roman">kmp</font><font face=宋体>的性质，</font><font face="Times New Roman">len-next[len]</font><font face=宋体>必为最短完全覆盖子序列的长度。所以我们肯定如果</font><font face="Times New Roman">S</font><font face=宋体>存在完全覆盖子序列的话，那么</font><font face="Times New Roman">len%(len-next[len])</font><font face=宋体>一定等于</font><font face="Times New Roman">0</font><font face=宋体>。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">那么是不是满足<font face="Times New Roman">len%(len-next[len])==0</font><font face=宋体>的串就一定有完全覆盖子序列呢？</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">设<font face="Times New Roman">next[len]=x.</font><font face=宋体>我们先考虑</font><font face="Times New Roman">x&lt;len/2</font><font face=宋体>的情况。显然</font><font face="Times New Roman">len-x&gt;len/2</font><font face=宋体>，显然</font><font face="Times New Roman">len%(len-next)</font><font face=宋体>不为</font><font face="Times New Roman">0</font><font face=宋体>，所以不满足有完全覆盖子序列的必要条件，我们不予考虑。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">现在，考虑<font face="Times New Roman">x&gt;=len/2</font><font face=宋体>的情况。假设满足</font><font face="Times New Roman">len%(len-x)==0</font><font face=宋体>时仍没有完全覆盖子序列。为了证明下面我们用了几个符号代表一些含义。设</font><font face="Times New Roman">y=len-x</font><font face=宋体>。因为</font><font face="Times New Roman">y|len,</font><font face=宋体>所以</font><font face="Times New Roman">y|(x+y),</font><font face=宋体>而</font><font face="Times New Roman">y|y</font><font face=宋体>，所以</font><font face="Times New Roman">y|x</font><font face=宋体>。用</font><font face="Times New Roman">X</font><font face=宋体>表示</font><font face="Times New Roman">S</font><font face=宋体>串中前</font><font face="Times New Roman">x</font><font face=宋体>个字符</font><font face="Times New Roman">(</font><font face=宋体>包括第</font><font face="Times New Roman">x</font><font face=宋体>个字符</font><font face="Times New Roman">)</font><font face=宋体>形成的子串，</font><font face="Times New Roman">Y</font><font face=宋体>表示自第</font><font face="Times New Roman">x</font><font face=宋体>个后面的</font><font face="Times New Roman">y</font><font face=宋体>个字符形成的子串。所以</font><font face="Times New Roman">X</font><font face=宋体>的长度为</font><font face="Times New Roman">x</font><font face=宋体>，</font><font face="Times New Roman">Y</font><font face=宋体>的长度为</font><font face="Times New Roman">y</font><font face=宋体>。因为</font><font face="Times New Roman">y|x,</font><font face=宋体>令</font><font face="Times New Roman">m=y/x</font><font face=宋体>，所以我们把</font><font face="Times New Roman">X</font><font face=宋体>分成</font><font face="Times New Roman">m</font><font face=宋体>等份，用</font><font face="Times New Roman">X1,X2...Xm</font><font face=宋体>表示。因为</font><font face="Times New Roman">next[len]=x</font><font face=宋体>，所以我们有</font><font face="Times New Roman">X1+X2+X3+...+Xm-1+Xm=X2+X3+...+Xm+Y</font><font face=宋体>。加号代表连接。即得到</font><font face="Times New Roman">X1=X2=X3=...=Xm=Y</font><font face=宋体>！我们发现了一个序列</font><font face="Times New Roman">Y</font><font face=宋体>可以完全覆盖主串</font><font face="Times New Roman">S</font><font face=宋体>，且该子串长为</font><font face="Times New Roman">y=len-x</font><font face=宋体>。这已之前的假设相冲突，于是我们肯定</font><font face="Times New Roman">len%(len-next[len])==0</font><font face=宋体>时，一定有完全覆盖子序列，且最短完全覆盖子序列长度为</font><font face="Times New Roman">len-next[len].</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; TEXT-INDENT: 21pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">证毕！</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
</div>
<!--endfragment-->
<img src ="http://www.cppblog.com/NARUTOACM/aggbug/110555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/NARUTOACM/" target="_blank">NARUTOACM</a> 2010-03-25 22:35 <a href="http://www.cppblog.com/NARUTOACM/archive/2010/03/25/110555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>树状数组</title><link>http://www.cppblog.com/NARUTOACM/archive/2010/03/21/110186.html</link><dc:creator>NARUTOACM</dc:creator><author>NARUTOACM</author><pubDate>Sat, 20 Mar 2010 16:27:00 GMT</pubDate><guid>http://www.cppblog.com/NARUTOACM/archive/2010/03/21/110186.html</guid><wfw:comment>http://www.cppblog.com/NARUTOACM/comments/110186.html</wfw:comment><comments>http://www.cppblog.com/NARUTOACM/archive/2010/03/21/110186.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/NARUTOACM/comments/commentRss/110186.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/NARUTOACM/services/trackbacks/110186.html</trackback:ping><description><![CDATA[<div style="LAYOUT-GRID:  15.6pt none" class=Section0>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">树状数组可以用来干嘛？树状数组可以用来快速求一个数组的和。。。。</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">当然这只是片面的，树状数组最大的好处就是支持处理一些动态的问题，它是一种高效的进行区间统计的数据结构。</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">它支持查询和修改操作，并且复杂度都是<font face="Times New Roman">log(n)</font><font face=宋体>级别的，可见树状数组的高效。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">看图说话<font face="Times New Roman">(</font><font face=宋体>摘自百度百科</font><font face="Times New Roman">)</font><font face=宋体>：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><img src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps_clip_image-138.png" width=464 height=297><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">看懂了这个图就基本掌握了树状数组了。</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">来观察这个图：</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">令这棵树的结点编号为<font face="Times New Roman">C1</font><font face=宋体>，</font><font face="Times New Roman">C2...Cn</font><font face=宋体>。令每个结点的值为这棵树的值的总和，那么容易发现：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C1&nbsp;=&nbsp;A1</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C2&nbsp;=&nbsp;A1&nbsp;+&nbsp;A2</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C3&nbsp;=&nbsp;A3</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C4&nbsp;=&nbsp;A1&nbsp;+&nbsp;A2&nbsp;+&nbsp;A3&nbsp;+&nbsp;A4</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C5&nbsp;=&nbsp;A5</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C6&nbsp;=&nbsp;A5&nbsp;+&nbsp;A6</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C7&nbsp;=&nbsp;A7</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C8&nbsp;=&nbsp;A1&nbsp;+&nbsp;A2&nbsp;+&nbsp;A3&nbsp;+&nbsp;A4&nbsp;+&nbsp;A5&nbsp;+&nbsp;A6&nbsp;+&nbsp;A7&nbsp;+&nbsp;A8</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">...</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">C16&nbsp;=&nbsp;A1&nbsp;+&nbsp;A2&nbsp;+&nbsp;A3&nbsp;+&nbsp;A4&nbsp;+&nbsp;A5&nbsp;+&nbsp;A6&nbsp;+&nbsp;A7&nbsp;+&nbsp;A8&nbsp;+&nbsp;A9&nbsp;+&nbsp;A10&nbsp;+&nbsp;A11&nbsp;+&nbsp;A12&nbsp;+&nbsp;A13&nbsp;+&nbsp;A14&nbsp;+&nbsp;A15&nbsp;+&nbsp;A16</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">这里有一个有趣的性质：</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">设节点编号为<font face="Times New Roman">x</font><font face=宋体>，那么这个节点管辖的区间为</font><font face="Times New Roman">2^k</font><font face=宋体>（其中</font><font face="Times New Roman">k</font><font face=宋体>为</font><font face="Times New Roman">x</font><font face=宋体>二进制末尾</font><font face="Times New Roman">0</font><font face=宋体>的个数）个元素。因为这个区间最后一个元素必然为</font><font face="Times New Roman">Ax</font><font face=宋体>，</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">所以很明显：<font face="Times New Roman">Cn&nbsp;=&nbsp;A(n&nbsp;</font><font face=宋体>&#8211;&nbsp;</font><font face="Times New Roman">2^k&nbsp;+&nbsp;1)&nbsp;+&nbsp;...&nbsp;+&nbsp;An</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">算这个<font face="Times New Roman">2^k</font><font face=宋体>有一个快捷的办法，定义一个函数如下即可：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">int&nbsp;lowbit(int&nbsp;x){</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">return&nbsp;x&amp;(x^(x<font face=宋体>&#8211;</font><font face="Times New Roman">1));</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">}</span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">当想要查询一个<font face="Times New Roman">SUM(n)</font><font face=宋体>时，可以依据如下算法即可：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">step1:<font face=宋体>令</font><font face="Times New Roman">sum&nbsp;=&nbsp;0</font><font face=宋体>，转第二步；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">step2:<font face=宋体>假如</font><font face="Times New Roman">n&nbsp;&lt;=&nbsp;0</font><font face=宋体>，算法结束，返回</font><font face="Times New Roman">sum</font><font face=宋体>值，否则</font><font face="Times New Roman">sum&nbsp;=&nbsp;sum&nbsp;+&nbsp;Cn</font><font face=宋体>，转第三步；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">step3:&nbsp;<font face=宋体>令</font><font face="Times New Roman">n&nbsp;=&nbsp;n&nbsp;</font><font face=宋体>&#8211;&nbsp;</font><font face="Times New Roman">lowbit(n)</font><font face=宋体>，转第二步。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">可以看出，这个算法就是将这一个个区间的和全部加起来，为什么是效率是<font face="Times New Roman">log(n)</font><font face=宋体>的呢？以下给出证明：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">n&nbsp;=&nbsp;n&nbsp;<font face=宋体>&#8211;&nbsp;</font><font face="Times New Roman">lowbit(n)</font><font face=宋体>这一步实际上等价于将</font><font face="Times New Roman">n</font><font face=宋体>的二进制的最后一个</font><font face="Times New Roman">1</font><font face=宋体>减去。而</font><font face="Times New Roman">n</font><font face=宋体>的二进制里最多有</font><font face="Times New Roman">log(n)</font><font face=宋体>个</font><font face="Times New Roman">1</font><font face=宋体>，所以查询效率是</font><font face="Times New Roman">log(n)</font><font face=宋体>的。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">那么修改呢，修改一个节点，必须修改其所有祖先，最坏情况下为修改第一个元素，最多有<font face="Times New Roman">log(n)</font><font face=宋体>的祖先。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">所以修改算法如下（给某个结点<font face="Times New Roman">i</font><font face=宋体>加上</font><font face="Times New Roman">x</font><font face=宋体>）：</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">step1:&nbsp;<font face=宋体>当</font><font face="Times New Roman">i&nbsp;&gt;&nbsp;n</font><font face=宋体>时，算法结束，否则转第二步；</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">step2:&nbsp;Ci&nbsp;=&nbsp;Ci&nbsp;+&nbsp;x<font face=宋体>，&nbsp;</font><font face="Times New Roman">i&nbsp;=&nbsp;i&nbsp;+&nbsp;lowbit(i)</font><font face=宋体>转第一步。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">i&nbsp;=&nbsp;i&nbsp;+lowbit(i)<font face=宋体>这个过程实际上也只是一个把末尾</font><font face="Times New Roman">1</font><font face=宋体>补为</font><font face="Times New Roman">0</font><font face=宋体>的过程。</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
<p style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt" class=p0><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'">对于数组求和来说树状数组简直太快了<font face="Times New Roman">!</font></span><span style="FONT-FAMILY: '宋体'; FONT-SIZE: 10.5pt; mso-spacerun: 'yes'"><o:p></o:p></span></p>
</div>
<!--endfragment-->
<img src ="http://www.cppblog.com/NARUTOACM/aggbug/110186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/NARUTOACM/" target="_blank">NARUTOACM</a> 2010-03-21 00:27 <a href="http://www.cppblog.com/NARUTOACM/archive/2010/03/21/110186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>