A new ways to solve range problems

Правка en1, от BFSDFS123qwq, 2023-01-04 04:42:59

I'm sorry that I'm a Chinese and most of the English name of algorithm I don't know. So, I use google translation to translate it.

Have you ever seen the following questions?

Calculate the median of a range, and you must finish online (means you need to calculate real question by using last answer). What would you do? If the problem is not online, we can easily use persistent segment tree to solve it. And now it is online, maybe you think you can solve it by using AVL.

Now, I will show you another way to solve this question. Divide the sequence into n blocks, each blocks' size is sqrt(n). For each block, we set a segment tree that contain the value of this block.

For a question of asking [l,r], we find the blocks that the whole block of it in the range. And we use segment tree merge to merge them. And for the number that is not contained by the complete block, we insert them into the segment tree.

And we get a segment tree that contain the value of the range. And we can use segment tree binary search to solve this problem.

There is a sample: We set a array of [1,1,4,2,1,3,1,4,3], and the picture below is the block number and segment trees of the array.  If we want to ask range [2,8], we will do this below:  And we can solve something on the new segment tree.

For the time limit. We set the numbers in the array is lower than m, there are n numbers in the array. Because of the size of the block is sqrt(n) and numbers of blocks are sqrt(n), so we mostly do segment tree merge for sqrt(n) times, and mostly insert the numbers into the segment tree for 2*sqrt(n) times. And then, the time of the segment tree merge is log2(m), insert the numbers are log2(m) too. So, this algorithm's time is O(n*sqrt(n)*log2(m)), We can solve it in 1 seconds when n and m are lower than 2e5.

But there is always a question, memory. Because we can't modify the value of the segment tree in the blocks. So we need to merge the segment tree in the blocks to the new segment tree. If we create a new segment tree for every query, the memory will not ok. So we only use one segment tree, and after every query, we clear it.

A possible code:

int l,r;
l=read(),r=read();
for(int i=l;i<=min(belong[l]*block,r);i++)
{
	update(root[nowroot],1,len,Ar[i],1);
}
if(belong[l]!=belong[r])
{
	for(int i=(belong[r]-1)*block+1;i<=r;i++)
	{
		update(root[nowroot],1,len,Ar[i],1);
	}
}
for(int i=belong[l]+1;i<=belong[r]-1;i++)
{
	merge(root[nowroot],root[i],1,len);
}

int ans=query(root[newroot]);
printf("%.4lf\n",ans);
clear(newroot); 

In this code, block is sqrt(n), query is a function of answering the problems, update is the function of inserting numbers, merge is the function of segment tree merge.

Do you think it's useless? Yes, by now, all it can finish, we can use AVL to solve it, and it needs a longer time. But I don't know what other problems this algorithm can solve. At least, we only need to learn one algorithm, congratulation! And I think that many people who issue the problems of data structure, they will set limit of n<=1e5 and not for 1e6!

Теги data structures, segment tree, segment trees, block

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
en9 Английский BFSDFS123qwq 2023-01-07 03:44:47 28
en8 Английский BFSDFS123qwq 2023-01-05 07:58:10 270
en7 Английский BFSDFS123qwq 2023-01-04 08:42:58 322 Tiny change: ' classmates [user:pzq' -> ' classmate [user:pzq'
en6 Английский BFSDFS123qwq 2023-01-04 06:12:42 5 Tiny change: 'nprintf("%.4lf\n",ans);\' -> 'nprintf("%d\n",ans);\'
en5 Английский BFSDFS123qwq 2023-01-04 04:52:15 1
en4 Английский BFSDFS123qwq 2023-01-04 04:45:47 0 (published)
en3 Английский BFSDFS123qwq 2023-01-04 04:45:22 76
en2 Английский BFSDFS123qwq 2023-01-04 04:44:17 4
en1 Английский BFSDFS123qwq 2023-01-04 04:42:59 3307 Initial revision (saved to drafts)