Merging investigation of P4198 building reconstruction line segment tree

Topic entry

In fact, this problem is not easy to see at the beginning. This is the problem of the line segment tree, but when we see the modification, nine times out of ten we are investigating the line segment tree. When we see whether the floor required by the problem surface can be seen, we think that the line segment tree maintains the slope (because only the floor with a large and high slope with the original point can be seen), The difficulty of this problem lies in how to maintain this line segment tree. The main limiting factor in this problem lies in the point closest to the origin, that is, the left half interval. Each point maintains the floors with only [l, R] interval. How many buildings can we see, that is, all floors except these intervals do not exist. The most difficult thing is how to merge these floors.

Let me introduce the idea of the big man first (konjaku is too tired to write)

From the valley of Los Angeles Nemlit mogul
display however close and area between of place yes floor room one set can with see reach Left edge of area between The first one individual position Set see Obviously, all buildings in the merged section must be able to see the first position of the section on the left Obviously, all buildings in the merged section must be able to see the first position of the section on the left reach of place yes floor room ( this answer Should very display however bar ) that Do you right area between And ? I Guys can with before check look for right area between of Left To all the buildings (this should be obvious). What about the right section? We can find the left of the right interval first To all the buildings (this should be obvious). What about the right section? We can find the left of the right interval first area between of most large value , as fruit this individual most large value than Left area between of most large value Small , that Do you yes area between of Left The maximum value of the interval. If the maximum value is smaller than the maximum value of the left interval, there is the left of the interval The maximum value of the interval. If the maximum value is smaller than the maximum value of the left interval, there is the left of the interval area between of place yes answer case one set see no reach , place with I Guys Just can with Deliver return check look for right area between of right area between as fruit right area between All the answers of the interval must not be visible, so we can recursively find the right interval of the right interval All the answers of the interval must not be visible, so we can recursively find the right interval of the right interval of Left area between of most large value than Left area between of most large value large , that Do you primary come cover right If the maximum value of the left interval is greater than the maximum value of the left interval, it will be replaced by the right one If the maximum value of the left interval is greater than the maximum value of the left interval, it will be replaced by the right one area between of Left area between block live of present stay one kind meeting cover block live , I Guys Just can with plus upper right area between of The left section of the section will be blocked now, so we can add the right section The left section of the section will be blocked now, so we can add the right section answer case , place with I Guys can with Deliver return check look for right area between of Left area between but yes this in So we can recursively find the left interval of the right interval, but here So we can recursively find the left interval of the right interval, but here yes one individual pit spot , yes area between of answer case no one set yes a n s a n s [ right area between of There is a pit, and the answer with interval is not necessarily ans[right interval There is a pit, and the answer with interval is not necessarily ans[right interval right area between ] , because by right area between of answer case can can cover Left area between block live , Right interval], because the answer of the right interval may be blocked by the left interval, Right interval], because the answer of the right interval may be blocked by the left interval, place with yes area between of answer case one set yes a n s a n s [ right area between ] − a n s a n s [ So the answer with an interval must be ansans [right interval] - ansans[ So the answer with an interval must be ansans [right interval] - ansans[ right area between of Left area between ] each second check Inquire of complex miscellaneous degree by O ( 1 ) O ( The complexity of each query is O (1) O( The complexity of each query is O (1) O( 1 ) , I Guys each second only meeting Deliver return one individual son son , place with each second check Inquire right 1) , we only recurse one son at a time, so each query right 1) , we only recurse one son at a time, so each query right son son answer case of complex miscellaneous degree by O ( l o g n ) O ( l o g n ) , so each second repair change of complex miscellaneous degree by The complexity of son's answer is O(logn)O(logn), so the complexity of each modification is The complexity of son's answer is O(logn)O(logn), so the complexity of each modification is O ( l o g 2 n ) O ( l o g 2 n ) his he of land square Just and universal through Line paragraph tree one kind Yes O(log^2n)O(log 2 n) other places are the same as ordinary segment trees O(log2n)O(log2n) other places are the same as ordinary segment trees

Finally, the code ends the problem

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std ;

const int N = 1e5 + 10 ;

int n , m ;
int read()
{
	char c ;
	int res = 0 , flag = 1 ;
	c = getchar() ;
	while(!isdigit(c))
	{
		if(c == '-') flag = -1 ;
		c = getchar() ;
	}
	while(isdigit(c))
	{
		res = (res << 1) + (res << 3) + (c ^ 48) ;
		c = getchar() ;
	}
	return res * flag ;
}

struct Node
{
	int l , r , cnt ;
	double val ; // Slope 
} tr[N * 4] ;

void build(int u , int l , int r)
{
	tr[u] = {l , r , 0 , 0} ;
	if(l == r) return ;
	int mid = l + r >> 1 ;
	build(u << 1 , l , mid) ;
	build(u << 1 | 1, mid + 1 , r) ;
}

int query(int u , double val)
{
	if(tr[u].val <= val) return 0 ;
	if(tr[u].l == tr[u].r) return 1 ;
	if(tr[u << 1].val <= val) return query(u << 1 | 1 , val) ;
	return query(u << 1 , val) + tr[u].cnt - tr[u << 1].cnt ; 
}
void change(int u , int pos , double x)
{
	if(tr[u].l == tr[u].r) 
	{
		tr[u].val = x ;
		tr[u].cnt = 1 ;
		return ;
	}
	int mid = tr[u].l + tr[u].r >> 1;
	if(pos <= mid) change(u << 1 , pos , x) ;
	else change(u << 1 | 1 , pos , x) ;
	tr[u].val = max(tr[u << 1].val , tr[u << 1 | 1].val) ;
	tr[u].cnt = tr[u << 1].cnt + query(u << 1 | 1 , tr[u << 1].val) ;
}
int main(void)
{
	n = read() , m = read() ;
	build(1 , 1 , n) ;
	for(int i = 1 ; i <= m ; i ++)
	{
		int x , h ;
		x = read() , h = read() ; 
		change(1 , x , h * 1.0 / x) ;
		printf("%d\n" , tr[1].cnt) ;
	}
}

Tags: Algorithm

Posted on Mon, 20 Sep 2021 01:48:57 -0400 by elthomo