Detailed Line Segment Tree - Shadow Width

OK, let’s talk about the line segment tree today~~

What is a segment tree

Line segment tree ( S segment SegmentSegment    T r e e ~~Tree   Tree ) is a binary tree for interval queries. Each node of the line segment tree represents an interval, the root node represents the entire interval, and the child nodes represent half of the interval. A typical application of line segment trees is to solve interval query problems, such as interval maximum value, interval minimum value, etc.

Implementation of segment tree

The construction process of line segment tree can be realized by recursion. Given an array arr arra rr , the root node of the line segment tree representsarr [ 0 ] arr[0]arr[0] a r r [ n − 1 ] arr[n-1] arr[n1 ] between interval sums (or other interval operations). The left child node of the root node representsarr [ 0 ] arr[0]arr[0] a r r [ ( n − 1 ) / 2 ] arr[(n-1)/2] arr[(n1 ) /2 ] , and the right child node representsarr [ ( n − 1 ) / 2 + 1 ] arr[(n-1)/2+1]arr[(n1)/2+1] a r r [ n − 1 ] arr[n-1] arr[n1 ] between intervals and . And so on, until the interval is divided into nodes of length 1.

Each node of the line segment tree will record some statistical information of the interval represented by the node, such as interval sum, interval maximum value, interval minimum value, etc. The statistical information can be calculated from the statistical information of the left child node and the right child node of the node.

When the interval to be queried overlaps with the interval represented by the current node, the query operation will continue to recurse downward. When the interval to be queried is exactly equal to the interval represented by the current node, the query operation can directly return the statistical information of the current node. When the interval to be queried is in the left half of the interval represented by the current node, the query operation will recurse to the left child node. When the interval to be queried is in the right half of the interval represented by the current node, the query operation will recurse to the right child node.

When the position to be updated is within the interval represented by the current node, the update operation will continue to recurse downwards. When updating to a leaf node, update the value at that position to the given new value. The update operation then recurses upward, passing the updated value to the parent node and recalculating the parent node's statistics.

Time Complexity of Line Segment Tree

The time complexity of line segment tree is O ( log ( n ) ) O(log(n))O ( l o g ( n )) where n is the length of the array. This is because building a line segment tree requires one operation per node, totalingO ( n ) O(n)O ( n ) time. The time complexity of the query operation isO ( log ( n ) ) O(log(n))O ( l o g ( n )) , because the query process is similar to binary search, each time the query range is reduced by half, at most recursivelog ( n ) log(n)l o g ( n ) times. The time complexity of the update operation is alsoO ( log ( n ) ) O(log(n))O(log(n))

Line segment tree is a very powerful data structure that can be used to solve various interval query problems. However, the application of segment trees is not limited to a time complexity of O ( log ( n ) ) O(log(n))O ( log ( n )) problems, it can also be combined with other data structures and algorithms to achieve more efficient solutions . For example, line segment trees can be used in combination with discretization, tree arrays, etc. to solve dynamic interval query problems. At the same time, the line segment tree can also be used to solve interval query problems in some special cases, such as dynamically maintaining the maximum and minimum values ​​in the sliding window.

Application of Segment Tree

Line segment trees are widely used, and the following are some common application scenarios:

  • Interval minimum/maximum value query : through the line segment tree can be in O ( log ( n ) ) O(log(n))Find the minimum or maximum of any interval in O ( log ( n )) time . This is very useful when dealing with dynamic data, such as dynamically maintaining the minimum and maximum values ​​of the sliding window.

  • Interval and query : Segment tree can be used to quickly calculate the sum of all elements in the interval. This is useful for problems such as solving consecutive subarray sums over the range of an array, or dealing with interval addition or interval update operations.

  • Interval update : The line segment tree can update a certain value in the interval to a new value. This is very useful when dealing with dynamically modifying data, such as modifying the value of a certain position in an array, or increasing all elements in a range by a fixed value.

  • Interval statistics : In addition to basic operations such as summation, minimum value, and maximum value, the line segment tree can also perform more complex interval statistical operations. For example, the kkth in the interval can be solved through the line segment treeK small elements, or how many different elements are in the statistical interval, etc.

  • Discretization : Discretization is a method of mapping continuous data into discrete intervals. By using the line segment tree, the discretization operation can be easily realized, and a large amount of continuous data can be mapped to a limited discrete interval, thereby reducing the data size and improving query efficiency.

  • Interval intersection query : the line segment tree can be used to determine whether two intervals intersect, and to calculate the intersection of two intervals. This is very useful in scenarios such as dealing with overlapping intervals and finding common intervals.

  • Interval coverage query : The line segment tree can be used to quickly find out whether a certain interval is completely covered, and calculate all the intervals that cover a certain interval. This is very useful in dealing with problems such as interval merging and interval segmentation.

A line segment tree is a very powerful and flexible data structure that can be extended and optimized as needed. By rationally designing the data structure and algorithm, the line segment tree can efficiently solve various interval query problems and improve the performance and scalability of the program.

Node structure of line segment tree

The node structure of a line segment tree generally includes the following attributes:

start and end: indicate the start and end positions of the interval represented by the current node.
A plug-in: depends on the topic

Other operations and optimizations

The line segment tree can also perform some other operations and optimizations, such as:

  • Lazy update : Use tags to delay updates, reduce the number of update operations, and improve efficiency.
  • Interval increment : Maintain the increment of the interval value instead of directly modifying the value of the interval, which can reduce the number of update operations.
  • Dynamic modification : It supports modification based on the original data without rebuilding the entire line segment tree.

Example - shadow width

Several boxes were scattered on the Elf King's table, and behind the table was a wall. As shown below. Now a beam of parallel light shines from the front of the table, casting the shadow of the box onto the wall. What is the total width of the shadow?
insert image description here

input and output format

input format

  • Line 1: the number of boxes N (1≤=N≤10000).
  • Lines 2...N+1: the starting position S and the ending position T of each box (1≤S, T≤100000).

output format

  • Line 1: Contains an integer representing the total width of the shadow.

Input and output samples

input sample

4
1 2
3 5
4 6
5 6

output sample

4

Example explanation

This is a pure version of the question! !

#include <bits/stdc++.h>
using namespace std;
const int N=120000;
int n,m,maxx,minn,a[N],b[N],cover[4*N];
void insert(int idx,int ll,int rr,int x,int y) {
    
    
	if (x<=ll && y>=rr)		//如果区间范围包含当前线段
		cover[idx]=1;
	if(cover[idx]==1)	//如果当前线段已经被标记了
		return;
	int mid=(ll+rr)/2;
	if (y<=mid)
		insert(idx*2,ll,mid,x,y);	//左子树递归
	else if (x>=mid)
		insert(idx*2+1,mid,rr,x,y);		//右子树递归
	else {
    
    		//拆分成两边,分别递归
		insert(idx*2,ll,mid,x,y);
		insert(idx*2+1,mid,rr,x,y);
	}
}
int count(int idx,int ll,int rr,int x,int y) {
    
    
	if (cover[idx]==1)		//如果当前线段被标记
		return rr-ll;		//返回长度
	if (rr-ll>1) {
    
    		//如果当前线段还是一个线段
		int mid=(ll+rr)/2;
		int tx=count(idx*2,ll,mid,x,y);
		int ty=count(idx*2+1,mid,rr,x,y);
		return tx+ty;
	}
	return 0;
}
int main() {
    
    
	scanf ("%d",&n);
	for (int i=1;i<=n;i++) {
    
    
		scanf("%d%d",&a[i],&b[i]);
		if (a[i]>maxx)
			maxx=a[i];
		if (a[i]<minn)
			minn=a[i];
		if (b[i]>maxx)
			maxx=b[i];
		if (b[i]<minn)
			minn=b[i];
		//一堆判断,求最大边界和最小边界
		//有时候 是输入的数
	}
	for (int i=1;i<=n;i++)
		insert(1,minn,maxx,a[i],b[i]);		//标记线段
	printf("%d",count(1,minn,maxx,minn,maxx));		//输出结果
	return 0;
}

Guess you like

Origin blog.csdn.net/DUXS11/article/details/132389658