[Most detailed explanation of the whole network]Part1.OpenJudge Baidu 2528:Mayor's posters Segment Tree

Posted by lonerunner on Wed, 14 Aug 2019 04:12:38 +0200

Welcome to the message!Part1.OpenJudge Skills 2528:Mayor's posters Part2.Segment Tree from Simple to Complex

Part1.100 Training 2528:Mayor's posters

Title link: http://bailian.openjudge.cn/p...

Idea 1: Brute Force, record and keep updating the most outside poster's ID. Scan once and count the number of different ID s at last.

Solution 2. Based on Segment-Tree.

Understand the basics of segment trees first.

    Build trees.The ID value (key value) of each node stores the ID of the outermost poster in the area.Setup of node key value id: Define -1 as no poster coverage, 0 as multiple poster coverage, id=1 to m as covered by the idth poster, segment tree as long as it goes down at 0, other direct statistical colors.Statistical ID may consider using arrays to simulate bitmaps.
        Query.The sign that you don't continue searching for your descendants on a path is that only one poster covers the area or when you encounter 1 to m, the bitmap is updated.Encountered -1 and stopped searching on the path.
        Scan for the bitmap to get the final result.

Code for Solution 2 :
Note that in the code below, I use -1 to indicate that there are multiple posters, and 0 to indicate that there are no multiple poster covers, which is inconsistent with the above.

//Poster, output number not covered

include<stdio.h>

struct node

{

int l,r; //Number of left and right children  

int st,mi,en;  

int id;  

}; //Segment Tree Simple One-Dimension

const int maxN = 50000002; //Number of nodes in the segment tree

const int maxL = 10000020; //Upper width of step

node segment_tree[maxN]; //Saves all nodes of the segment tree

define tree segment_tree

int root, ptr;

void insert(int cr, int start, int end, int color)//insert into the specified area, initializing all nodes along the way

{

if(start >= end) //Input requirements not met  

    return;  

if(tree[cr].st == start && tree[cr].en == end) //The input interval is exactly equal to the representation interval of the node  

{  

    tree[cr].id = color; //This section belongs to the poster  

    return;  

}  

int mid = (tree[cr].st + tree[cr].en) / 2;  

if(tree[cr].l == 0) //This means that the child node has not been initialized yet  

{  

    //ptr represents the number of the node  

    tree[cr].l = ptr++;  

    tree[tree[cr].l].l = tree[tree[cr].l].r = 0;  

    tree[tree[cr].l].id = -1;  

    tree[tree[cr].l].st = tree[cr].st, //Initialize the range of left and right children here  

    tree[tree[cr].l].en = mid;  

}  

if(tree[cr].r == 0)  

{  

    tree[cr].r = ptr++;  

    tree[tree[cr].r].l = tree[tree[cr].r].r = 0;  

    tree[tree[cr].r].id = -1;  

    tree[tree[cr].r].st = mid,  

    tree[tree[cr].r].en = tree[cr].en;  

}  



if(tree[cr].id != 0) //All subsequent subdivisions must belong to the poster  

{  

    tree[tree[cr].l].id = tree[tree[cr].r].id = tree[cr].id;  

    tree[cr].id = 0;  

}  



if(start >= mid){  

    insert(tree[cr].r, start, end, color);  

    return;  

}  

if(end <= mid){  

    insert(tree[cr].l, start, end, color);  

    return;  

}  

insert(tree[cr].l, start, mid, color);  

insert(tree[cr].r, mid, end, color);  

}

char exist[10001];

void trail(int cr)//Statistics visible node numbers

{

if(cr == 0 || tree[cr].id == -1)  

    return;  

exist[tree[cr].id] = 1; //The id is not zero, which means that only it is visible, but later nodes are invisible.  

if(tree[cr].id != 0) //Not zero means the area behind will be covered.  

    return;  

trail(tree[cr].l);  

trail(tree[cr].r);  

}

//Initialize Follow Node

void init()

{

root = 1;  

tree[root].l = tree[root].r = tree[root].id = 0;  

tree[root].st = 1, tree[root].en = maxL, tree[root].mi = (1 + maxL)/2;  

ptr = 2;  

}

int main()

{

int test,n,i,l,r;  

scanf("%d", &test);  

while(test--)  

{  

    init();  

    scanf("%d",&n);  

    for(i = 1; i <= n; i++)  

    {  

        scanf("%d%d",&l,&r);  

        insert(1, l, r+1, i); //Insert from root node  

    }  

    for(i = 1; i <= n; i++)  

        exist[i] = 0;  

    trail(1);  

    int ans = 0;  

    for(i = 1; i <= n; i++)  

        if(exist[i])  

            ans++;  

    printf("%d\n",ans);  

}  

return 0;  

}

Part2. A detailed explanation of segment trees from simple to complex problems

Catalog

A review of segment trees
Flow of segment tree update operation
Example: Practice OJ-Poster
Segment Tree Model Selected for this Topic
Core data structure and algorithm steps
c++ Code Implementation

A review of segment trees

Segment Tree, Legend:

Figure 1
这里写图片�述

Interpretation of Figure 1:
A[l,r] represents the interval [l, r], A[t] represents the interval [t,t]
The segment tree describes the array in the graph
Number of array elements N is the number of leaf nodes
2N - 1 is the total number of nodes
A[l,r] is the numeric value of the corresponding interval
Leaf node is the value of a single element
Nonleaf nodes are the sum of child nodes

//An interval corresponds to a node
struct TreeNode
{

 
  int l,r;        // Left or right boundary of an interval
  int data;   // Maximum and minimum values in an interval, and the extreme values of an interval (maximum minus minimum)
                    // The ID of the outermost cover of an interval, id = 0, indicates that there is no cover on the outermost layer; id = -1 indicates that there are multiple cover on the outermost layer

}node[2*N]//The entire segment tree is represented by an array

The child of node[i] is node[2i+1] node[2i+2] //i starts with o

[l,r] is set to (1) [l,mid], [mid.r] or (2) [l.mid],[mid+1,r], as needed.
A general discrete model, the array selection model shown in Figure 1 (2)
The poster exercises that follow discretize the continuous model require selecting the model (1), otherwise the actual continuous segment [mid,mid+1] is not represented.

Meaning of non-leaf nodes;

It can be the sum of child nodes, the maximum and minimum of child nodes, etc.

Segment trees are like binary search trees, heaps

Node Meaning of Segment Tree. Tip 2: Tip 2 in the Node Meaning page of Segment Tree in Little Hi Hall

Application Scenario Model:
Interval problem, which reduces query time complexity to O (logn), stores corresponding data through a balanced binary tree by using additional space (non-leaf nodes, Figure 1) to record the value of an interval.
"Interval problem": the sum of an interval, the maximum and minimum values in the interval, and the extreme value of the interval (maximum minus minimum)

The implementation of segment tree data structure;
Array implementation, array implementation of analog heap

References for the above: WeChat Article Search. Beyond Technology. Illustrated Segment Tree

Segment Tree Creation, Query, Update

https://blog.csdn.net/gl48654...

Update of Segment Tree

Update A[4] to 666
Purple is the lookup path, and the values of all ancestors of A[4] are updated, lookups can be implemented recursively, and ancestor values can optionally be updated at the end of each recursion

To be sorted out:
Creation of segment tree: WeChat article search. Beyond technology. No data structure, no drawing today

Typical Question - Find the range of a data range from a stack of data, range = maximum - Minimum

Title Description
There are many trees along the road in Zijinshan. The height of each tree is recorded as H. h is a positive integer of class int. Trees are numbered from the beginning of the road to the end of the road.
1, 2, 3, 4...N (n<100,000).Now the height difference between trees a and B is the height of the tallest tree in [a,b] minus the height of the shortest tree.

Answer request time limit: 2000ms, memory limit: 64MB
input
The second row of positive integers, N and Q, respectively, indicates N trees and Q (Q<=10000) queries.
The third line has N positive integers.
The following Q lines have a, b for each line.Represents the first tree, the second tree, respectively (a)

output
For each query, output the height of the tall tree.

Sample
Input Sample 1 Replication

6 3
1 7 3 4 2 5
1 5
4 6
2 2
Output Sample 1

6
3
0

//An interval corresponds to a node
struct TreeNode
{

  int l,r;        // Left or right boundary of an interval
  int maxV;   // Maximum and minimum values in an interval, and the extreme values of an interval (maximum minus minimum)
  int minV;

}node[2*N]//The entire segment tree is represented by an array

//An interval corresponds to a node
class TreeNode {
public:

int l, r;      //  Left or right boundary of an interval
int maxV;   //  Maximum and minimum values in an interval, and the extreme values of an interval (maximum minus minimum)
int minV;

TreeNode(int l, int r) {
    this->l = l;
    this->r = r;
}

TreeNode() {

}

};

TreeNode g_node[3 * N]; //The entire segment tree is represented by an array

// g_node[i] has a child who is g_node[2i] g_node[2i + 1]// I starting from 1
// [l,r] children are set to (1) [l, mid], [mid.r] or (2) [l.mid],[mid+1,r], as needed.
//Select here (2), in addition to the following "Poster Example", general selection (2), Poster is continuous interval discretization, [mid, mid +1]
//is real and cannot be lost

int g_A[N];

/Tree building/
TreeNode build(int i, int l, int r) {

 g_node[i].l = l;
g_node[i].r = r;
if (l == r) {
    g_node[i].maxV = g_A[l];
    g_node[i].minV = g_A[l];
    return g_node[i];
}

int mid = l + (r - l) / 2;

build(2 * i, l, mid);
build(2 * i + 1, mid + 1, r);

g_node[i].maxV = max(g_node[2 * i].maxV, g_node[2 * i + 1].maxV);
g_node[i].minV = min(g_node[2 * i].minV, g_node[2 * i + 1].minV);

return g_node[i];

}

/ Query Min /
int queryMin(int i, int l, int r) { // i is the index of a g_node

if (l < g_node[i].l || r > g_node[i].r)//  wrong parameters
    return -1000;
if (l == g_node[i].l && r == g_node[i].r) return g_node[i].minV;

if (g_node[i].l == g_node[i].r) return g_node[i].minV;

//This cannot be written as if(l == r), otherwise i=1 will return node[i].minV directly.
// if(l == r) return g_node[i].minV; //error

int mid = g_node[i].l + (g_node[i].r - g_node[i].l) / 2;
if (r <= mid) return queryMin(2 * i, l, r);
if (l >= mid + 1) return queryMin(2 * i + 1, l, r);
return min(queryMin(2 * i, l, mid), queryMin(2 * i + 1, mid + 1, r));

}

/ Query Max/
int queryMax(int i, int l, int r) { // i is the index of a g_node

if (l < g_node[i].l || r > g_node[i].r)//  wrong parameters
    return -1000;

if (l == g_node[i].l && r == g_node[i].r) return g_node[i].maxV;

if (g_node[i].l == g_node[i].r) return g_node[i].maxV; 

//This cannot be written as if(l == r), otherwise i=1 will return node[i].maxV directly.
// if(l == r) return g_node[i].maxV; //error

int mid = g_node[i].l + (g_node[i].r - g_node[i].l) / 2;
if (r <= mid) return queryMax(2 * i, l, r);
if (l >= mid + 1) return queryMax(2 * i + 1, l, r);
return max(queryMax(2 * i, l, mid), queryMax(2 * i + 1, mid + 1, r));

}

int main() {

int n, q, a, b;

cin >> n >> q;
for (int i = 1; i < n + 1; ++i) {
    scanf("%d", g_A + i);
}
build(1, 1, n);

while (q--) {
    cin >> a >> b;
    if (a == b) {
        cout << 0 << endl;
        break;
    }
    int tmp = a;
    a = min(a, b);
    b = max(tmp, b);
    cout << queryMax(1, a, b) - queryMin(1, a, b) << endl;
}
return 0;

}

Segment Tree Modeling for Example (Poster)

Violence: Mark the number of the outermost poster on each unit and make statistics at the end.Time O (lgN*K) Space O (N+K) Total length N, number of posters K
Optimizing Method: Segment Tree Method

Segment Tree Modeling for this topic:

The discrete intervals in the segment tree shown above are [l,mid],[mid,r] instead of [l,mid],[mid+1,r]:

As to why this can be contradicted~~How do I store a poster between [mid,mid+1]?

If the number of leaf nodes is N, the total number of nodes is 2 N

Core data structure and algorithm steps:

node{ // a segment

int st; //Start coordinates
int en; //End coordinates
int  id; //The number of the outermost poster on this node.id = 0 means no poster cover, -1 means more than one poster cover

}

typedef segment node;

1. Build a tree and enter all poster information. If the current node.id >0, the information does not have to be passed on to the child nodes.Time O(Klog2N)
2. Statistically, the first segment of the A[i] tag appears at the outermost level, and the A[i] information is updated recursively starting from the root node. If the current node.id <= 0, there is no need to traverse the child nodes.Time (log2N)
3. Scan A[i] for final results, O(K)

Code implementation for poster:

//Poster, output number not covered

include<stdio.h>

struct node

{

int l,r; //Number of left and right children  

int st,mi,en;  

int id;  

}; //Segment Tree Simple One-Dimension

const int maxN = 50000002; //Number of nodes in the segment tree

const int maxL = 10000020; //Upper width of step

node segment_tree[maxN]; //Saves all nodes of the segment tree

define tree segment_tree

int root, ptr;

void insert(int cr, int start, int end, int color)//insert into the specified area, initializing all nodes along the way

{

if(start >= end) //Input requirements not met  

    return;  

if(tree[cr].st == start && tree[cr].en == end) //The input interval is exactly equal to the representation interval of the node  

{  

    tree[cr].id = color; //This section belongs to the poster  

    return;  

}  

int mid = (tree[cr].st + tree[cr].en) / 2;  

if(tree[cr].l == 0) //This means that the child node has not been initialized yet  

{  

    //ptr represents the number of the node  

    tree[cr].l = ptr++;  

    tree[tree[cr].l].l = tree[tree[cr].l].r = 0;  

    tree[tree[cr].l].id = -1;  

    tree[tree[cr].l].st = tree[cr].st, //Initialize the range of left and right children here  

    tree[tree[cr].l].en = mid;  

}  

if(tree[cr].r == 0)  

{  

    tree[cr].r = ptr++;  

    tree[tree[cr].r].l = tree[tree[cr].r].r = 0;  

    tree[tree[cr].r].id = -1;  

    tree[tree[cr].r].st = mid,  

    tree[tree[cr].r].en = tree[cr].en;  

}  



if(tree[cr].id != 0) //All subsequent subdivisions must belong to the poster  

{  

    tree[tree[cr].l].id = tree[tree[cr].r].id = tree[cr].id;  

    tree[cr].id = 0;  

}  



if(start >= mid){  

    insert(tree[cr].r, start, end, color);  

    return;  

}  

if(end <= mid){  

    insert(tree[cr].l, start, end, color);  

    return;  

}  

insert(tree[cr].l, start, mid, color);  

insert(tree[cr].r, mid, end, color);  

}

char exist[10001];

void trail(int cr)//Statistics visible node numbers

{

if(cr == 0 || tree[cr].id == -1)  

    return;  

exist[tree[cr].id] = 1; //The id is not zero, which means that only it is visible, but later nodes are invisible.  

if(tree[cr].id != 0) //Not zero means the area behind will be covered.  

    return;  

trail(tree[cr].l);  

trail(tree[cr].r);  

}

//Initialize Follow Node

void init()

{

root = 1;  

tree[root].l = tree[root].r = tree[root].id = 0;  

tree[root].st = 1, tree[root].en = maxL, tree[root].mi = (1 + maxL)/2;  

ptr = 2;  

}

int main()

{

int test,n,i,l,r;  

scanf("%d", &test);  

while(test--)  

{  

    init();  

    scanf("%d",&n);  

    for(i = 1; i <= n; i++)  

    {  

        scanf("%d%d",&l,&r);  

        insert(1, l, r+1, i); //Insert from root node  

    }  

    for(i = 1; i <= n; i++)  

        exist[i] = 0;  

    trail(1);  

    int ans = 0;  

    for(i = 1; i <= n; i++)  

        if(exist[i])  

            ans++;  

    printf("%d\n",ans);  

}  

return 0;  

}

Example - Calculate the total length of the segment coverage

WeChat Search. Informatics Competition. Segment Tree for OI Provincial Selection Algorithms (1)

Topics: C++