A new ways to solve range problems

Revision en2, by BFSDFS123qwq, 2023-01-04 04:44:17

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!

Tags data structures, segment tree, segment trees, block

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en9 English BFSDFS123qwq 2023-01-07 03:44:47 28
en8 English BFSDFS123qwq 2023-01-05 07:58:10 270
en7 English BFSDFS123qwq 2023-01-04 08:42:58 322 Tiny change: ' classmates [user:pzq' -> ' classmate [user:pzq'
en6 English BFSDFS123qwq 2023-01-04 06:12:42 5 Tiny change: 'nprintf("%.4lf\n",ans);\' -> 'nprintf("%d\n",ans);\'
en5 English BFSDFS123qwq 2023-01-04 04:52:15 1
en4 English BFSDFS123qwq 2023-01-04 04:45:47 0 (published)
en3 English BFSDFS123qwq 2023-01-04 04:45:22 76
en2 English BFSDFS123qwq 2023-01-04 04:44:17 4
en1 English BFSDFS123qwq 2023-01-04 04:42:59 3307 Initial revision (saved to drafts)