- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
代码 #includeiostream #includecstdio using namespace std; int n; int levels[32001]; int c[32001]; int lowbit(int x){ return x(-x); } 代码(续1) int sum(int x) { int s=0; while(x0){ s+=c[x]; x-=lowbit(x); } return s; } 代码(续2) void update(int pos) { while(pos=32001){ c[pos]++; pos+=lowbit(pos); } } 代码(续3) int main() { scanf(%d,n); int x,y; for(int i=1;i=n;i++){ scanf(%d %d,x,y); levels[sum(x+1)]++; update(x+1); } for(int i=0;in;i++){ printf(%d\n,levels[i]); } return 0; } ACM程序设计 第六讲 树状数组和线段树 相同点:一个节点表示一个线段 不同点: 线段树用二分思想表示这个线段 树状数组不是 原数据为a[],树状数组为c[],则 c[n]表示的段是 c[n]=a[n-2^k+1]+…+a[n] 其中k为n在二进制下末尾0的个数 例如n=6(110),对应k就是1 树状数组结构图 如何根据n计算2^k 2^k=n and (n xor(n-1)) Lowbit(x)就是根据n返回2^k Int Lowbit(int x) { return x(x^(x-1));//等价语句 return x(-x); } 树状数组的主要工作 和线段树类似: 查询 更新 查询 由c[]求原数据中区间[a,b]的和 sum(a,b)=sum(1,b)-sum(1,a-1) int sum(int end) { int sum=0; while(end0){ sum+=c[end]; end-=Lowbit(end); } return sum; } 算法就是将一个个区间和加起来,复杂度O(logn) 更新 给原数据a[x]加上一个数 因为每个c[]中元素表示一段,所以可能有多个c中元素包含a[x],这些c中元素都需要更新 void update(int pos,int num) { while(pos=N){ c[pos]+=num; pos+=Lowbit(pos); } } 修改一个节点,必须修改其所有祖先,最坏情形是修改第一个元素,最多有log n个祖先 树状数组局限性 树状数组不适合对一个区间进行更新 树状数组不适合对一个点进行查询 树状数组一般只适合:对点更新;对区间查询 对区间查询要进行转化 sum(a,b)=sum(1,b)-sum(1,a-1) 不满足这个规则的也不能用树状数组 若对区间更新;对点查询,可以将sum函数和update函数内部实现调换一下,这样复杂度不变,但此时c[]已经不是定义上的树状数组了 二维树状数组更新 void update(int i,int j,int k) { while(i=n){ int temp=j; while(temp=n){ c[i][temp]+=k; temp+=Lowbit(temp); } i+=Lowbit(i); } } 二维树状数组查询 int sum(int i,int j) { int sum; while(i0){ int temp=j; while(temp0){ sum+=c[i][temp]; temp-=Lowbit(temp); } i-=Lowbit(i); } return sum; } 树状数组和线段树比较 很多情况下,线段树可以用树状数组实现 能用树状数组解决的问题一定能用线段树解决 题目不满足减法原则,只能用线段树 (求一段数字中的最大或最小,就不能用树状数组) 树状数组是进行区间
文档评论(0)