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

ACM___________________________

______________白白の屋
posts - 182, comments - 102, trackbacks - 0, articles - 0
<2010年10月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

常用鏈接

留言簿(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>
            尤物在线观看一区| 一本色道久久综合精品竹菊| 亚洲午夜影视影院在线观看| 亚洲另类自拍| 欧美日韩免费在线| 午夜精品久久久久久99热| 亚洲伊人网站| 国内精品久久久久久| 免费观看久久久4p| 欧美成人三级在线| 亚洲综合色自拍一区| 亚洲欧美伊人| 影音先锋日韩精品| 亚洲电影一级黄| 欧美午夜不卡影院在线观看完整版免费| 亚洲色图自拍| 性高湖久久久久久久久| 亚洲第一久久影院| 一区二区三区黄色| 1000部国产精品成人观看| 亚洲精品乱码久久久久久日本蜜臀 | 蜜月aⅴ免费一区二区三区| 亚洲美女黄网| 亚洲欧美日韩国产成人精品影院 | 另类综合日韩欧美亚洲| 在线一区二区三区做爰视频网站 | 嫩草成人www欧美| 欧美日精品一区视频| 久久免费精品视频| 欧美视频精品在线| 免费观看国产成人| 国产精品视频网址| 最近中文字幕mv在线一区二区三区四区| 欧美日韩国产区一| 久久久一区二区| 欧美三级小说| 亚洲黄色免费网站| 国内精品国产成人| 亚洲视频在线观看一区| 亚洲精品一区二区在线观看| 亚洲免费在线| 亚洲美女在线看| 久久精品国产亚洲精品| 亚洲视频精选| 欧美国产日韩在线| 久久综合伊人77777尤物| 欧美午夜在线观看| 亚洲区在线播放| 在线精品视频免费观看| 午夜精品福利一区二区三区av| 99精品福利视频| 欧美1区2区3区| 蜜臀av在线播放一区二区三区| 国产精品欧美久久久久无广告| 亚洲国产成人精品久久| 在线观看成人小视频| 欧美在线二区| 欧美在线观看视频一区二区三区 | 欧美破处大片在线视频| 欧美不卡在线| 在线观看成人一级片| 久久成人18免费观看| 久久成人羞羞网站| 国产精品一二三四| 亚洲网在线观看| 亚洲欧美日韩综合一区| 国产精品99免视看9| 99精品欧美一区| 亚洲午夜精品一区二区| 欧美日韩一区二区免费视频| 亚洲精品视频中文字幕| 一本色道久久加勒比88综合| 欧美日本久久| 亚洲天堂男人| 久久精品国产99国产精品| 国产婷婷色一区二区三区四区| 午夜精彩视频在线观看不卡 | 亚洲大胆人体视频| 欧美成人一区二区三区在线观看 | 亚洲综合精品自拍| 国产农村妇女精品| 久久久久看片| 亚洲区在线播放| 亚洲欧美精品在线| 国模 一区 二区 三区| 久久香蕉国产线看观看网| 亚洲国产精品精华液2区45| 亚洲图片欧洲图片av| 国产伦精品一区二区三区免费 | 亚洲欧美日韩久久精品| 久久免费视频一区| 亚洲国产欧美另类丝袜| 欧美日韩亚洲91| 亚洲欧美日韩在线高清直播| 看片网站欧美日韩| 亚洲图片激情小说| 黄色成人av网| 欧美午夜精品久久久久久久| 午夜精品亚洲| 亚洲青涩在线| 久久综合亚州| 一区二区欧美在线| 精东粉嫩av免费一区二区三区| 欧美另类变人与禽xxxxx| 欧美一级午夜免费电影| 亚洲福利视频网站| 欧美一区二区三区免费在线看| 亚洲国产岛国毛片在线| 欧美新色视频| 欧美成年人视频网站| 亚洲欧美一区二区精品久久久| 亚洲高清视频在线| 久久久久久久综合| 在线视频你懂得一区二区三区| 黄色一区二区在线观看| 国产精品毛片| 欧美精选午夜久久久乱码6080| 久久国产主播精品| 亚洲欧美日韩电影| 一本色道**综合亚洲精品蜜桃冫| 免费在线观看一区二区| 欧美在线视频一区二区三区| 一区二区三区欧美| 亚洲福利视频二区| 狠狠入ady亚洲精品| 国产精品免费区二区三区观看| 欧美另类videos死尸| 免费观看在线综合| 久久久久国色av免费看影院| 中文日韩电影网站| 亚洲美女啪啪| 亚洲精品乱码久久久久久蜜桃91| 免费久久99精品国产自| 久久久久久久一区| 久久精品欧美日韩精品| 午夜欧美精品久久久久久久| 亚洲手机在线| 亚洲图片欧美一区| 亚洲在线成人| 亚洲综合二区| 亚洲欧美日韩中文在线制服| 亚洲视频在线二区| 亚洲四色影视在线观看| 一区二区欧美激情| 亚洲一区二区三区影院| 亚洲调教视频在线观看| 亚洲一区欧美| 欧美一级黄色网| 久久精品国产99精品国产亚洲性色 | 久久久精品一品道一区| 久久久久亚洲综合| 免费观看成人网| 欧美激情精品久久久久| 亚洲国产天堂久久综合网| 91久久久久久久久| 一区二区三区欧美视频| 亚洲一级在线观看| 午夜欧美精品久久久久久久| 欧美中文日韩| 美日韩免费视频| 欧美日韩网址| 国产精品腿扒开做爽爽爽挤奶网站| 国产精品久久一卡二卡| 国产一区二区三区观看 | 欧美三级黄美女| 国产欧美精品在线观看| 激情欧美亚洲| 99精品国产福利在线观看免费 | 99视频一区| 午夜精品视频在线观看一区二区| 久久精彩免费视频| 欧美国产日韩xxxxx| 日韩小视频在线观看专区| 亚洲欧美在线免费观看| 久久阴道视频| 国产精品久久夜| 亚洲高清在线观看| 亚洲午夜羞羞片| 蜜桃av噜噜一区二区三区| 亚洲区第一页| 久久国产精品色婷婷| 欧美另类极品videosbest最新版本| 国产精品亚洲综合久久| 又紧又大又爽精品一区二区| 亚洲视频在线一区| 美日韩精品视频| 一区二区三区欧美成人| 久久午夜国产精品| 国产精品亚洲综合一区在线观看| 在线观看欧美日韩| 亚洲欧美日韩爽爽影院| 亚洲黄色在线| 久久嫩草精品久久久精品一| 国产精品美女久久久久av超清 | 国产乱码精品| 中文欧美字幕免费| 欧美激情一区二区久久久| 欧美一区二区网站| 国产精品欧美一区喷水| 99国产精品久久久久久久久久|