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

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>
            激情视频亚洲| 蜜臀a∨国产成人精品| 美女在线一区二区| 快射av在线播放一区| 久久精品国产一区二区三区免费看| 亚洲高清一区二区三区| 亚洲黄色一区| 亚洲尤物影院| 午夜精品在线视频| 久久久国产一区二区| 欧美v日韩v国产v| 欧美日韩在线不卡一区| 国产精品日韩精品欧美在线| 国产日韩欧美在线观看| 在线观看中文字幕不卡| 亚洲免费观看在线视频| 先锋影音一区二区三区| 欧美91视频| 一级日韩一区在线观看| 欧美淫片网站| 欧美精品久久久久a| 国产老肥熟一区二区三区| 午夜国产精品视频| 欧美日韩国产va另类| 亚洲专区免费| 久久蜜桃香蕉精品一区二区三区| 免费观看一区| 国产伦精品一区二区三区| 91久久精品国产91久久性色tv| 亚洲网站在线看| 六月天综合网| 亚洲在线网站| 欧美激情久久久| 国产精品揄拍500视频| 亚洲美女黄网| 鲁大师影院一区二区三区| 亚洲午夜激情免费视频| 欧美成人激情视频免费观看| 国产一区视频观看| 亚洲高清中文字幕| 国产精品白丝黑袜喷水久久久 | 久热精品视频在线观看| 国产日韩欧美黄色| 亚洲日本免费| 久久综合给合久久狠狠狠97色69| 亚洲精品一区二区三区樱花| 久久精品亚洲一区二区| 国产精品午夜电影| 宅男66日本亚洲欧美视频| 欧美成人一区二区三区在线观看 | 亚洲视频电影在线| 亚洲视频在线观看网站| 亚洲欧美日韩区| 久久成人综合网| 中日韩美女免费视频网站在线观看| 欧美一级视频精品观看| 国产精品乱人伦中文| 亚洲私人影院在线观看| 亚洲国产精品毛片| 欧美jizz19性欧美| 亚洲国产欧美不卡在线观看| 麻豆国产精品一区二区三区| 欧美一区亚洲二区| 国产一区二区在线观看免费| 久久爱另类一区二区小说| 小处雏高清一区二区三区| 国产午夜精品一区理论片飘花| 欧美一区二区日韩| 在线性视频日韩欧美| 亚洲福利视频三区| 99国产精品久久| av成人毛片| 欧美日韩亚洲综合一区| 亚洲日韩成人| 日韩午夜视频在线观看| 欧美日韩伊人| 欧美在线观看视频在线| 欧美主播一区二区三区美女 久久精品人| 国产精品一区二区你懂得 | 久久av老司机精品网站导航| 国产一区二区毛片| 男人的天堂成人在线| 欧美成人一区二区在线 | 99国产精品久久久久久久| 亚洲欧美在线观看| 亚洲欧美中文另类| 国产日韩三区| 久久精品国产亚洲一区二区| 裸体歌舞表演一区二区 | 鲁大师影院一区二区三区| 国产婷婷成人久久av免费高清| 性久久久久久| 最新中文字幕一区二区三区| av成人激情| 国产精品黄页免费高清在线观看| 老司机精品视频一区二区三区| 国产日本欧美在线观看 | 免费在线亚洲| 欧美精品一区二区视频| 午夜国产精品影院在线观看| 久久精品99久久香蕉国产色戒| 99国产精品99久久久久久| 午夜精品一区二区在线观看 | 久久综合色影院| 中文欧美日韩| 久久久蜜桃一区二区人| 亚洲一区二区三区四区视频| 久久久免费av| 欧美一级视频精品观看| 欧美激情片在线观看| 久久午夜av| 国产伦精品一区二区三区| 日韩视频永久免费观看| 在线免费观看日本欧美| 在线亚洲欧美视频| 亚洲国产日本| 久久黄色网页| 久久精品国产一区二区电影| 欧美吻胸吃奶大尺度电影| 欧美激情五月| 精品电影在线观看| 午夜欧美精品| 午夜一级在线看亚洲| 欧美精品成人在线| 欧美激情中文字幕乱码免费| 国产主播精品| 欧美诱惑福利视频| 久久久91精品国产| 国产三级精品在线不卡| 亚洲一区二区欧美日韩| 亚洲午夜三级在线| 欧美无砖砖区免费| 韩国成人福利片在线播放| 99精品国产在热久久下载| 久久视频免费观看| 久久一区二区三区四区五区| 国产欧美日韩综合| 亚洲欧美日韩国产一区二区三区| 亚洲免费黄色| 欧美片网站免费| 日韩亚洲成人av在线| 一本色道久久综合亚洲精品按摩| 你懂的视频一区二区| 亚洲第一主播视频| 亚洲人成网站影音先锋播放| 欧美ed2k| 99综合视频| 欧美亚洲网站| 国产精品中文字幕欧美| 西西人体一区二区| 久久久久久久综合日本| 韩国av一区二区三区四区| 久久久一区二区| 欧美激情偷拍| 亚洲一区二区免费在线| 国产精品九九久久久久久久| 亚洲欧美日韩一区二区三区在线 | 午夜精品一区二区三区在线播放| 国产精品久久久久国产精品日日| 亚洲一区在线免费观看| 久久久夜夜夜| 亚洲精品视频免费观看| 国产精品swag| 欧美一区二区三区在线视频 | 一本久久综合亚洲鲁鲁| 欧美一级免费视频| **网站欧美大片在线观看| 欧美高清视频www夜色资源网| 一区二区三区精密机械公司| 久久精品一区二区| 亚洲精品久久久久| 国产精品一区二区黑丝| 美女脱光内衣内裤视频久久影院| 日韩天天综合| 老鸭窝91久久精品色噜噜导演| 99re6这里只有精品| 国产午夜精品福利| 欧美二区在线播放| 香蕉久久精品日日躁夜夜躁| 亚洲承认在线| 久久不射2019中文字幕| 亚洲免费av观看| 国产一区二区三区久久久| 欧美精品一区在线| 久久久999成人| 亚洲性视频网址| 亚洲欧洲一区二区三区| 久久综合色一综合色88| 亚洲欧美影音先锋| 一区二区久久久久久| 好吊视频一区二区三区四区| 国产精品久久久久久亚洲调教| 免费在线视频一区| 久久久成人精品| 亚洲欧美在线一区| 亚洲午夜视频在线| 日韩视频在线一区二区三区| 亚洲成色777777在线观看影院| 久久婷婷蜜乳一本欲蜜臀| 蜜桃av一区二区三区|