青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

ACM___________________________

______________白白の屋
posts - 182, comments - 102, trackbacks - 0, articles - 0
<2010年8月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
2930311234

常用鏈接

留言簿(24)

隨筆分類(332)

隨筆檔案(182)

FRIENDS

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

評論排行榜

By boba5551
TopCoder Member

Introduction

We often need some sort of data structure to make our algorithms faster. In this article we will
discuss the Binary Indexed Trees structure. According to Peter M. Fenwick, this structure was first used for data compression. Now it is often used for storing frequencies and manipulating cumulative frequency tables.

Let's define the following problem: We have n boxes. Possible queries are

1. add marble to box i

2. sum marbles from box k to box l

The naive solution has time complexity of O(1) for query 1 and O(n) for query 2. Suppose we make m queries. The worst
case (when all queries are 2) has time complexity O(n * m). Using some data structure (i.e.
RMQ) we can solve this
problem with the worst case time complexity of O(m log n). Another approach is to use Binary Indexed Tree data structure,
also with the worst time complexity O(m log n) -- but Binary Indexed Trees are much easier to code, and require less memory
space, than RMQ.

Notation

BIT - Binary Indexed Tree

MaxVal - maximum value which will have non-zero frequency

f[i] - frequency of value with index ii = 1 .. MaxVal

c[i] - cumulative frequency for index i (f[1] + f[2] + ... + f[i])

tree[i] - sum of frequencies stored in BIT with index i
(latter will be described what index means); sometimes we will write tree frequency instead
sum of frequencies stored in BIT

num¯ - complement of integer num (integer where each binary digit is inverted: 0 -> 1; 1 -> 0 )

NOTE: Often we put f[0] = 0, c[0] = 0, tree[0] = 0, so sometimes I will just ignore index 0.

Basic idea

Each integer can be represented as sum of powers of two. In the same way, cumulative frequency can be
represented as sum of sets of subfrequencies. In our case, each set contains some successive number of non-overlapping frequencies.

idx is some index of BITr is a position in idx of the last digit 1
(from left to right) in binary notation. tree[idx] is sum of frequencies from index (idx - 2^r + 1) to
index idx (look at the Table 1.1 for clarification). We also write that idx is responsible for
indexes from (idx - 2^r + 1) to idx (note that responsibility is the key in our algorithm and
is the way of manipulating the tree).

12345678910111213141516
f1021130425223102
c1134588121419212326272729
tree1124140122721134029

Table 1.1

12345678910111213141516
tree11..231..455..671..899..10119..121313..14151..16

Table 1.2 - table of responsibility

Image 1.3 - tree of responsibility for indexes (bar shows range of frequencies accumulated in top element)

Image 1.4 - tree with tree frequencies

Suppose we are looking for cumulative frequency of index 13 (for the first 13 elements). In binary notation,
13 is equal to 1101. Accordingly, we will calculate c[1101] = tree[1101] + tree[1100] + tree[1000]
(more about this later).

Isolating the last digit

NOTE: Instead of "the last non-zero digit," it will write only "the last digit."

There are times when we need to get just the last digit from a binary number, so we need an
efficient way to do that. Let num be the integer whose last digit we want to isolate. In binary
notation num can be represented as a1b, where a represents binary digits before the last digit and
b represents zeroes after the last digit.

Integer -num is equal to (a1b)¯ + 1 = a¯0b¯ + 1b consists of all zeroes, so 
consists of all ones. Finally we have

-num = (a1b)¯ + 1 = a¯0b¯ + 1 = a¯0(0...0)¯ + 1 = a¯0(1...1) + 1 = a¯1(0...0) = a¯1b.

Now, we can easily isolate the last digit, using bitwise operator AND (in C++, Java it is &) with num and -num:


a1b

&      a¯1b

--------------------

= (0...0)1(0...0)

Read cumulative frequency

If we want to read cumulative frequency for some integer idx, we add to sum tree[idx], substract
last bit of idx from itself (also we can write - remove the last digit; change the last digit to zero)
and repeat this while idx is greater than zero. We can use next function (written in C++)

int read(int idx){
	int sum = 0;
	while (idx > 0){
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

Example for idx = 13; sum = 0:

iterationidxposition of the last digitidx & -idxsum
113 = 110101 (2 ^0)3
212 = 110024 (2 ^2)14
38 = 100038 (2 ^3)26
40 = 0---------

Image 1.5 - arrows show path from index to zero which we use to get sum (image shows example for index 13)

So, our result is 26. The number of iterations in this function is number if bits in idx, which is at most log MaxVal.

Time complexity: O(log MaxVal).

Code length: Up to ten lines.

Change frequency at some position and update tree

The concept is to update tree frequency at all indexes which are responsible for frequency whose value we are changing. In reading cumulative frequency at some index,
we were removing the last bit and going on. In changing some frequency val in tree, we should increment value at the current index (the starting index is always the
one whose frequency is changed) for val, add the last digit to index and go on while the index is less than or equal to MaxVal. Function in C++:

void update(int idx ,int val){
	while (idx <= MaxVal){
		tree[idx] += val;
		idx += (idx & -idx);
	}
}

Let's show example for idx = 5:

iterationidxposition of the last digitidx & -idx
15 = 10101 (2 ^0)
26 = 11012 (2 ^1)
38 = 100038 (2 ^3)
416 = 10000416 (2 ^4)
532 = 100000------

Image 1.6 - Updating tree (in brackets are tree frequencies before updating); arrows show path while we update tree from index to MaxVal (image shows example for index 5)

Using algorithm from above or following arrows shown in Image 1.6 we can update BIT.

Time complexity: O(log MaxVal).

Code length: Up to ten lines.

Read the actual frequency at a position

We've described how we can read cumulative frequency for an index. It is obvious that
we can not read just tree[idx] to get the actual frequency for value at index idx. One approach is to have
one aditional array, in which we will seperately store frequencies for values. Both reading and storing take O(1); memory
space is linear. Sometimes it is more important to save memory, so we will show how you can get actual
frequency for some value without using aditional structures.

Probably everyone can see that the actual frequency at a position idx can be calculated by calling function read
twice -- f[idx] = read(idx) - read(idx - 1) -- just by taking the difference of two adjacent cumulative frequencies.
This procedure always works in 2 * O(log n) time. If we write a new function, we can get a bit faster algorithm, with smaller const.

If two paths from two indexes to root have the same part of path, then we can calculate the sum until the paths meet,
substract stored sums and we get a sum of frequencies between that two indexes. It is pretty simple
to calculate sum of frequencies between adjacent indexes, or read the actual frequency at a given index.

Mark given index with x, its predecessor with y. We can represent (binary notation) y as a0b,
where b consists of all ones. Then, x will be a1b¯ (note that  consists all zeros).
Using our algorithm for getting sum of some index, let it be x, in first iteration we remove the last
digit, so after the first iteration x will be a0b¯, mark a new value with z.

Repeat the same process with y. Using our function for reading sum we will remove the last digits
from the number (one by one). After several steps, our y will become (just to remind, it was a0b)
a0b¯, which is the same as z. Now, we can write our algorithm. Note that the only exception is when x
is equal to 0. Function in C++:

int readSingle(int idx){
int sum = tree[idx]; // sum will be decreased
if (idx > 0){ // special case
	int z = idx - (idx & -idx); // make z first
	idx--; // idx is no important any more, so instead y, you can use idx
	while (idx != z){ // at some iteration idx (y) will become z
		sum -= tree[idx];
// substruct tree frequency which is between y and "the same path"
		idx -= (idx & -idx);
	}
}
return sum;
}

Here's an example for getting the actual frequency for index 12:

First, we will calculate z = 12 - (12 & -12) = 8sum = 11

iterationyposition of the last digity & -ysum
111 = 101101 (2 ^0)9
210 = 101012 (2 ^1)2
38 = 1000---------

Image 1.7 - read actual frequency at some index in BIT
(image shows example for index 12)

Let's compare algorithm for reading actual frequency at some index when we twice use function read and
the algorithm written above. Note that for each odd number, the algorithm will work in const time O(1), without any iteration. For
almost every even number idx, it will work in c * O(log idx), where c is strictly less than 1, compare to
read(idx) - read(idx - 1), which will work in c1 * O(log idx), where c1 is always greater than 1.

Time complexity: c * O(log MaxVal), where c is less than 1.

Code length: Up to fifteen lines.

Scaling the entire tree by a constant factor

Sometimes we want to scale our tree by some factor. With the procedures described above it is very simple.
If we want to scale by some factor c, then each index idx should be updated by
-(c - 1) * readSingle(idx) / c (because f[idx] - (c - 1) * f[idx] / c = f[idx] / c). Simple function in C++:

void scale(int c){
	for (int i = 1 ; i <= MaxVal ; i++)
		update(-(c - 1) * readSingle(i) / c , i);
}

This can also be done more quickly. Factor is linear operation. Each tree frequency is a linear composition of some frequencies.
If we scale each frequency for some factor, we also scaled tree frequency for the same factor. Instead of rewriting the procedure above, which has time complexity O(MaxVal * log MaxVal), we can achieve time complexity
of O(MaxVal):

void scale(int c){
	for (int i = 1 ; i <= MaxVal ; i++)
		tree[i] = tree[i] / c;
}

Time complexity: O(MaxVal).

Code length: Just a few lines.

Find index with given cumulative frequency

The naive and most simple solution for finding an index with a given cumultive frequency
is just simply iterating through all indexes, calculating cumulative frequency, and checking if it's equal to
the given value. In case of negative frequencies it is the only solution. However,
if we have only non-negative frequencies in our tree (that means cumulative frequencies for greater indexes are not smaller)
we can figure out logarithmic algorithm, which is modification of binary search. We go through
all bits (starting with the highest one), make the index, compare the cumulative frequency of the current index and given
value and, according to the outcome, take the lower or higher half of the interval (just like in binary search). Function in C++:

// if in tree exists more than one index with a same
// cumulative frequency, this procedure will return
// some of them (we do not know which one)

// bitMask - initialy, it is the greatest bit of MaxVal
// bitMask store interval which should be searched
int find(int cumFre){
	int idx = 0; // this var is result of function 

	while ((bitMask != 0) && (idx < MaxVal)){ // nobody likes overflow :)
		int tIdx = idx + bitMask; // we make midpoint of interval
		if (cumFre == tree[tIdx]) // if it is equal, we just return idx
			return tIdx;
		else if (cumFre > tree[tIdx]){
		        // if tree frequency "can fit" into cumFre,
		        // then include it
			idx = tIdx; // update index 
			cumFre -= tree[tIdx]; // set frequency for next loop 
		}
		bitMask >>= 1; // half current interval
	}
	if (cumFre != 0) // maybe given cumulative frequency doesn't exist
		return -1;
	else
		return idx;
}

// if in tree exists more than one index with a same
// cumulative frequency, this procedure will return
// the greatest one
int findG(int cumFre){
	int idx = 0;

	while ((bitMask != 0) && (idx < MaxVal)){
		int tIdx = idx + bitMask;
		if (cumFre >= tree[tIdx]){
		        // if current cumulative frequency is equal to cumFre,
		        // we are still looking for higher index (if exists)
			idx = tIdx;
			cumFre -= tree[tIdx];
		}
		bitMask >>= 1;
	}
	if (cumFre != 0)
		return -1;
	else
		return idx;
}

Example for cumulative frequency 21 and function find:

First iterationtIdx is 16; tree[16] is greater than 21; half bitMask and continue
Second iterationtIdx is 8; tree[8] is less than 21, so we should include first 8 indexes in result, remember idx because we surely know it is part of result;
subtract tree[8] of cumFre (we do not want to look for the same cumulative frequency again - we are looking for another cumulative frequency in the
rest/another part of tree); half bitMask and contiue
Third iterationtIdx is 12; tree[12] is greater than 9 (there is no way to overlap interval 1-8, in this example,
with some further intervals, because only interval 1-16 can overlap); half bitMask and continue
Forth iterationtIdx is 10; tree[10] is less than 9, so we should update values; half bitMask and continue
Fifth iterationtIdx is 11; tree[11] is equal to 2; return index (tIdx)

Time complexity: O(log MaxVal).

Code length: Up to twenty lines.

2D BIT

BIT can be used as a multi-dimensional data structure. Suppose you have a plane with dots (with non-negative
coordinates). You make three queries:

  1. set dot at (x , y)
  2. remove dot from (x , y)
  3. count number of dots in rectangle (0 , 0), (x , y) - where (0 , 0) if down-left corner, (x , y) is up-right corner and
    sides are parallel to x-axis and y-axis.

If m is the number of queries, max_x is maximum x coordinate, and max_y is maximum y coordinate, then
the problem should be solved in O(m * log (max_x) * log (max_y)). In this case, each element of the tree will contain
array - (tree[max_x][max_y]). Updating indexes of x-coordinate is the same as before. For example, suppose we are setting/removing dot
(a , b). We will call update(a , b , 1)/update(a , b , -1), where update is:

void update(int x , int y , int val){
	while (x <= max_x){
		updatey(x , y , val);
		// this function should update array tree[x] 
		x += (x & -x);
	}
}

The function updatey is the "same" as function update:

void updatey(int x , int y , int val){
	while (y <= max_y){
		tree[x][y] += val;
		y += (y & -y);
	}
}

It can be written in one function/procedure:

void update(int x , int y , int val){
	int y1;
	while (x <= max_x){
		y1 = y;
		while (y1 <= max_y){
			tree[x][y1] += val;
			y1 += (y1 & -y1);
		}
		x += (x & -x);
	}
}

Image 1.8 - BIT is array of arrays, so this is two-dimensional BIT (size 16 x 8).
Blue fields are fields which we should update when we are updating index (5 , 3).

The modification for other functions is very similar. Also, note that BIT can be used as an n-dimensional data structure.

Sample problem

  • SRM 310 - FloatingMedian
  • Problem 2:Statement:There is an array of n cards. Each card is putted face down on table. You have two queries:

    1. T i j (turn cards from index i to index j, include i-th and j-th card - card which was
    face down will be face up; card which was face up will be face down)

    2. Q i (answer 0 if i-th card is face down else answer 1)

    Solution:

    This has solution for each query (and 1 and 2) has time complexity O(log n). In array
    f (of length n + 1) we will store each query T (i , j) - we set f[i]++ and
    f[j + 1]--. For each card k between i and j (include i and j) sum
    f[1] + f[2] + ... + f[k] will be increased for 1, for all others will be same as before (look at the
    image 2.0 for clarification), so our solution will be described sum (which is same as cumulative frequency) module 2.

    Image 2.0

    Use BIT to store (increase/decrease) frequency and read cumulative frequency.

Conclusion

  • Binary Indexed Trees are very easy to code.
  • Each query on Binary Indexed Tree takes constant or logarithmic time.
  • Binary Indexeds Tree require linear memory space.
  • You can use it as an n-dimensional data structure.



青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一二三区精品| 欧美成人免费网站| 久久最新视频| 鲁大师影院一区二区三区| 久久综合网hezyo| 欧美成人免费在线观看| 亚洲精品极品| 亚洲精品美女在线观看| 亚洲视频网在线直播| 亚洲自啪免费| 久久在线免费观看视频| 欧美精品三级| 国产一区二区在线观看免费| 亚洲激情视频在线播放| 亚洲免费影视| 欧美激情精品久久久久久变态| 亚洲精品乱码久久久久久蜜桃91| 亚洲午夜精品久久久久久app| 久久久一区二区| 国产精品久久久久免费a∨| 在线日韩日本国产亚洲| 欧美一级理论性理论a| 亚洲电影激情视频网站| 亚洲天堂网在线观看| 久久欧美中文字幕| 国产精品久久久久免费a∨| 1000部国产精品成人观看| 亚洲一区二区在线免费观看视频| 久久综合久久久久88| 亚洲天堂网站在线观看视频| 免费毛片一区二区三区久久久| 国产精品素人视频| 亚洲免费av片| 免费永久网站黄欧美| 亚洲制服丝袜在线| 欧美日韩高清在线一区| 在线看国产日韩| 久久国产精品久久久| 一二三四社区欧美黄| 免费成人av在线| 国产自产2019最新不卡| 午夜精品国产精品大乳美女| 亚洲精品欧美| 久久麻豆一区二区| 国产综合网站| 久久久蜜臀国产一区二区| 亚洲女同性videos| 国产精品一区二区三区观看| 在线亚洲成人| 一区二区三区黄色| 国产午夜亚洲精品理论片色戒| 免费观看成人www动漫视频| 国产精品人人做人人爽人人添| 亚洲免费观看高清完整版在线观看熊| 久久亚洲二区| 久久婷婷成人综合色| 在线观看成人av电影| 久久青草久久| 久久久国产一区二区| 国内精品视频在线观看| 久久精品夜色噜噜亚洲a∨ | 久久亚洲综合网| 欧美亚洲视频在线看网址| 国产女人水真多18毛片18精品视频| 亚洲影院免费| 亚洲性夜色噜噜噜7777| 国产精品久久久久久久一区探花| 一本到高清视频免费精品| 日韩视频免费在线观看| 国产精品福利在线观看网址| 亚洲欧美成人一区二区在线电影| 亚洲一区二区三区精品动漫| 国产日韩欧美在线观看| 老巨人导航500精品| 你懂的成人av| 亚洲一区二区三区777| 亚洲欧美日韩爽爽影院| 在线观看亚洲精品视频| 亚洲人成在线观看网站高清| 欧美亚洲第一区| 久久麻豆一区二区| 欧美国产日韩精品| 亚洲男人的天堂在线| 欧美有码视频| 日韩午夜激情电影| 亚洲视频一区在线| 精品999在线播放| 日韩视频永久免费观看| 国产小视频国产精品| 亚洲福利免费| 国产女主播在线一区二区| 欧美激情四色| 国产美女精品视频免费观看| 欧美福利一区二区| 国产精品视频自拍| 欧美韩日精品| 国产亚洲欧美一区二区三区| 亚洲国产裸拍裸体视频在线观看乱了中文 | 久久精品一区二区三区不卡| 亚洲国产精品一区二区久| 一二三区精品福利视频| 黄色一区二区三区四区| 日韩一区二区福利| ●精品国产综合乱码久久久久| 亚洲免费一区二区| 国产一区二区三区视频在线观看 | 久久综合电影| 欧美三级网址| 欧美国产在线观看| 国产麻豆综合| 99re热精品| 最新国产成人在线观看| 欧美在线免费观看| 午夜精品在线观看| 欧美日韩精品一区二区| 欧美高清在线一区二区| 国产亚洲aⅴaaaaaa毛片| 亚洲美女av在线播放| 亚洲国产成人精品视频| 欧美一区在线视频| 亚洲欧美在线免费| 欧美日韩人人澡狠狠躁视频| 亚洲第一中文字幕在线观看| 国产一区久久| 午夜在线精品| 久久精品91| 国产手机视频一区二区| 亚洲手机成人高清视频| 亚洲一区二区三区在线视频| 欧美区一区二区三区| 亚洲激情婷婷| 亚洲黄色在线看| 免费人成网站在线观看欧美高清| 巨乳诱惑日韩免费av| 樱花yy私人影院亚洲| 久久久久国产精品厨房| 玖玖在线精品| 最新日韩精品| 欧美黄污视频| 99精品欧美一区二区三区| 亚洲免费在线视频一区 二区| 欧美午夜片欧美片在线观看| 亚洲视频福利| 久久精品国产99| 精品成人久久| 欧美/亚洲一区| 夜夜嗨av一区二区三区四区| 午夜精品在线看| 黄色精品一区| 欧美国产欧美亚洲国产日韩mv天天看完整 | 亚洲精品免费一区二区三区| 欧美激情精品久久久六区热门| 欧美激情视频网站| 在线视频免费在线观看一区二区| 欧美日韩午夜视频在线观看| 亚洲一区二区三区影院| 久久久精品tv| 亚洲黄色小视频| 欧美视频中文在线看| 亚洲欧美成人在线| 免费观看国产成人| 在线综合+亚洲+欧美中文字幕| 国产精品老女人精品视频| 欧美一级欧美一级在线播放| 欧美好骚综合网| 亚洲一级黄色| 国产在线拍偷自揄拍精品| 久久久久久久高潮| 久久一区亚洲| 日韩视频一区二区三区在线播放免费观看 | 日韩视频在线一区二区| 国产精品每日更新| 久久这里只有| 正在播放亚洲一区| 欧美成人午夜77777| 国产精品99久久久久久有的能看| 国产一区二区电影在线观看 | 欧美视频中文在线看| 欧美一区二视频在线免费观看| 亚洲国产综合91精品麻豆| 久久本道综合色狠狠五月| 亚洲国产清纯| 国产一区二区久久精品| 欧美精品在线观看一区二区| 欧美在线视频全部完| 日韩亚洲欧美一区| 亚洲国产婷婷香蕉久久久久久| 欧美自拍丝袜亚洲| 亚洲尤物影院| 亚洲免费精彩视频| 一区二区在线观看视频| 欧美性做爰猛烈叫床潮| 欧美不卡在线视频| 久久亚洲国产精品一区二区| 亚洲欧美另类综合偷拍| 99国产精品国产精品久久| 亚洲电影观看| 亚洲风情亚aⅴ在线发布| 久久综合狠狠综合久久综青草 | 日韩一区二区精品|