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

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>
            欧美91精品| 久久久久综合| 亚洲精品欧美精品| 欧美在线视频免费播放| 免费视频一区二区三区在线观看| 亚洲网站视频福利| 欧美激情按摩在线| 欧美国产日本韩| 国产一区二区视频在线观看 | 亚洲视频在线观看三级| 91久久精品日日躁夜夜躁国产| 香蕉亚洲视频| 午夜欧美大尺度福利影院在线看| 欧美久久久久久久久久| 91久久国产精品91久久性色| 黄色成人免费网站| 欧美亚洲尤物久久| 久久成人精品视频| 国产美女精品视频| 亚洲欧美在线免费观看| 校园激情久久| 久久久久综合一区二区三区| 久久精品国产一区二区三区| 国产视频观看一区| 香蕉久久a毛片| 久久久久免费| 精品福利av| 鲁大师成人一区二区三区| 久久亚洲综合色一区二区三区| 国产一区二区三区的电影| 久久av二区| 美女尤物久久精品| 在线播放日韩欧美| 99精品欧美一区二区蜜桃免费| 99国内精品久久| 欧美日韩亚洲在线| 亚洲一区尤物| 久久人人97超碰国产公开结果| 黄色日韩网站视频| 免费短视频成人日韩| 亚洲欧洲另类| 亚洲女人天堂成人av在线| 国产欧美日韩在线播放| 久久免费视频观看| 亚洲欧美日韩一区在线观看| 国产精品日韩欧美| 久久精品国产99国产精品澳门| 欧美福利视频在线观看| 日韩视频免费在线| 国产精品午夜春色av| 久久久亚洲精品一区二区三区| 欧美激情一区二区三区 | 亚洲黄色免费电影| 欧美日韩综合不卡| 久久久久综合| 国产精品99久久久久久www| 久久久久国产免费免费| 亚洲欧洲精品一区二区三区不卡| 欧美日韩在线不卡一区| 欧美一区二区观看视频| 亚洲国产天堂久久综合| 午夜精品久久久久久久久久久久久 | 欧美日韩一区高清| 欧美一区二区| 亚洲精品少妇30p| 久久精品av麻豆的观看方式| 亚洲精品欧美极品| 国产一区二区三区无遮挡| 欧美成人69av| 久久成人精品视频| 亚洲最新视频在线播放| 欧美成人高清视频| 欧美制服丝袜第一页| 亚洲欧洲免费视频| 国产一区二区三区四区在线观看| 欧美剧在线观看| 久久国产精品一区二区三区四区 | 欧美日韩国产三区| 久久久久久尹人网香蕉| 亚洲欧洲在线播放| 欧美**人妖| 性久久久久久| 一区二区三区回区在观看免费视频 | 亚洲视频在线观看网站| 欧美福利在线| 久久另类ts人妖一区二区| 亚洲一区欧美二区| 日韩视频不卡| 亚洲欧洲日夜超级视频| 国内精品久久久久久久影视麻豆| 欧美午夜激情视频| 欧美日韩国产美女| 欧美激情一区二区三区四区| 久久久www成人免费毛片麻豆| 亚洲免费网址| 亚洲性线免费观看视频成熟| 亚洲美女一区| 日韩写真在线| 一本色道久久综合一区 | 亚洲一区高清| 日韩午夜免费视频| 9l国产精品久久久久麻豆| 亚洲人体影院| 亚洲国产成人久久综合一区| 欧美成ee人免费视频| 久久人人97超碰精品888| 久久久久久久久久久一区 | 亚洲视频自拍偷拍| 日韩一二三区视频| 亚洲一二三区视频在线观看| 亚洲美女黄色| 亚洲一区二区三区精品视频| 这里只有精品视频| 亚洲亚洲精品三区日韩精品在线视频 | 99精品国产高清一区二区| 亚洲毛片一区二区| av成人毛片| 亚洲天堂网在线观看| 亚洲在线日韩| 久久精品日韩| 欧美 日韩 国产精品免费观看| 欧美va亚洲va香蕉在线| 欧美高清在线精品一区| 亚洲黄色免费| 一区二区三区免费网站| 亚洲午夜一区二区| 久久精品二区| 欧美丰满高潮xxxx喷水动漫| 欧美日韩的一区二区| 国产欧美不卡| 亚洲成人在线观看视频| 99精品国产福利在线观看免费| 亚洲欧美激情四射在线日| 久久久av网站| 亚洲国产综合在线| 亚洲在线免费观看| 久久久水蜜桃av免费网站| 欧美精品激情| 国产色产综合色产在线视频| 在线观看亚洲一区| 亚洲午夜精品一区二区| 久久久精品性| 亚洲精品综合| 久久精品噜噜噜成人av农村| 欧美激情精品久久久久| 国产精品天美传媒入口| 亚洲国产精品久久人人爱蜜臀| 国产精品99久久久久久久vr | 欧美1级日本1级| 在线亚洲电影| 久久婷婷国产综合尤物精品| 欧美午夜无遮挡| 亚洲国产精品成人va在线观看| 亚洲午夜久久久| 欧美成人中文字幕| 亚洲一区二区三区涩| 免费人成精品欧美精品| 国产精品一区久久久久| 亚洲精品之草原avav久久| 久久国产精品99国产| 亚洲激情网站| 久久久久久久欧美精品| 国产精品久久久久一区二区三区| 亚洲激情午夜| 久久综合久久久| 亚洲性线免费观看视频成熟| 欧美另类一区二区三区| 精品福利免费观看| 欧美一区二区三区久久精品| 日韩亚洲精品电影| 欧美激情精品久久久久久| 国内成+人亚洲+欧美+综合在线| 亚洲伊人一本大道中文字幕| 91久久综合亚洲鲁鲁五月天| 久久精品国产久精国产爱| 国产精品一区二区久久久久| 亚洲私人影吧| 9国产精品视频| 欧美精品一区在线观看| 最新热久久免费视频| 欧美多人爱爱视频网站| 久久久噜噜噜久噜久久| 国产一级揄自揄精品视频| 性做久久久久久| 亚洲一区二区视频| 国产精品久久久久久久久久久久| 国产又爽又黄的激情精品视频| 亚洲欧美99| 亚洲性图久久| 国产精品免费久久久久久| 亚洲图片你懂的| 亚洲美女免费精品视频在线观看| 欧美高清在线视频观看不卡| 亚洲人成毛片在线播放| 亚洲第一中文字幕在线观看| 久久免费精品视频| 亚洲日本精品国产第一区| 亚洲国产精品va在线看黑人| 欧美不卡在线| 一区二区三区不卡视频在线观看|