POJ2352 树状数组

2024-02-29 10:48
文章标签 数组 树状 poj2352

本文主要是介绍POJ2352 树状数组,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

POJ2352

假设数组a[1..n],那么查询a[1]+...+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别。 来观察这个图: 令这棵树的结点编号为C1,C2...Cn。令每个结点的值为这棵树的值的总和,那么容易发现: C1 = A1 C2 = A1 + A2 C3 = A3 C4 = A1 + A2 + A3 + A4 C5 = A5 C6 = A5 + A6 C7 = A7 C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 ... C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16 这里有一个有趣的性质: 设节点编号为x,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ax, 所以很明显:Cn = A(n – 2^k + 1) + ... + An 算这个2^k有一个快捷的办法,定义一个函数如下即可: 1 2 3 int lowbit(int x){ return x&(x^(x–1)); } 利用机器补码特性,也可以写成: 1 2 3 int lowbit(int x){ return x&-x; } 当想要查询一个SUM(n)(求a[n]的和),可以依据如下算法即可: step1: 令sum = 0,转第二步; step2: 假如n <= 0,算法结束,返回sum值,否则sum = sum + Cn,转第三步; step3: 令n = n – lowbit(n),转第二步。 可以看出,这个算法就是将这一个个区间的和全部加起来,为什么是效率是log(n)的呢?以下给出证明: n = n – lowbit(n)这一步实际上等价于将n的二进制的最后一个1减去。而n的二进制里最多有log(n)个1,所以查询效率是log(n)的。 那么修改呢,修改一个节点,必须修改其所有祖先,最坏情况下为修改第一个元素,最多有log(n)的祖先。 所以修改算法如下(给某个结点i加上x): step1: 当i > n时,算法结束,否则转第二步; step2: Ci = Ci + x, i = i + lowbit(i)转第一步。 i = i +lowbit(i)这个过程实际上也只是一个把末尾1补为0的过程。 对于数组求和来说树状数组简直太快了! 注: 求lowbit(x)的建议公式: lowbit(x):=x and -x; 或lowbit(x):=x and (x xor (x - 1)); lowbit(x)即为2^k的值。

==================================================================================

http://www.cnblogs.com/hsd-/p/6139376.html

==================================================================================

#include<cstdio>
#include<iostream>
using namespace std;#define N 32005
int c[N] = {0};
int a[N] = {0};
int lowbit(int x)
{return (x)&(-x);
}void update(int pos, int add)
{while(pos < N){c[pos] += add;pos += lowbit(pos);}
}int getsum(int pos)
{int sum = 0;while(pos > 0){sum += c[pos];pos -= lowbit(pos);}return sum;
}int main()
{int n;while(~scanf("%d",&n)){int x,y;memset(a, 0, sizeof(a));memset(c, 0, sizeof(c));for(int i=1;i<=n;i++){scanf("%d%d",&x,&y);update(x+1,1);a[getsum(x+1)]++;}for(int i=1;i<=n;i++){printf("%d\n",a[i]);}}
}

 

posted @ 2017-10-31 10:04 swallowblank 阅读(...) 评论(...) 编辑 收藏

这篇关于POJ2352 树状数组的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/758503

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[

Go 数组赋值问题

package mainimport "fmt"type Student struct {Name stringAge int}func main() {data := make(map[string]*Student)list := []Student{{Name:"a",Age:1},{Name:"b",Age:2},{Name:"c",Age:3},}// 错误 都指向了最后一个v// a

码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)

1🐋🐋配对最小值(王者;树状数组) 时间限制:1秒 占用内存:64M 🐟题目思路 MT3065 配对最小值_哔哩哔哩_bilibili 🐟代码 #include<bits/stdc++.h> using namespace std;const int N=1e5+7;int a[N],b[N],c[N],n,q;struct QUERY{int l,r,id;}que

【第0006页 · 数组】寻找重复数

【前言】本文以及之后的一些题解都会陆续整理到目录中,若想了解全部题解整理,请看这里: 第0006页 · 寻找重复数         今天想讨论的一道题在 LeetCode 上评论也是颇为“不错”。有一说一,是道好题,不过我们还是得先理解了它才算真正的好题。这里我们展示一种使用二进制的做法,希望能帮到你哟! 【寻找重复数】给定一个包含 n + 1 个整数的数组 nums ,其数字都