Line segment tree-Mayor's posters

【topic】

Topic link

【analysis】

  1. It is still a question that is considered backwards. The poster is traversed from back to front. If there is a wall that has not been pasted, then the current poster is visible (the meaning of the variable ok)
  2. As the value range of the tiles is too large, we adopt a discretization method, taking "the starting point of the poster" and " a point behind the end of the poster (important idea) " as the starting point of the fragment. Collect all the starting points, sort them, and remove the duplicates. Then, when you need to access the subscript of the starting point of the clip according to the starting point of the poster, use binary search. (In this code, set is used for de-duplication, in fact, it is better to use unique function directly)
  3. tree[root]=1 if and only if all segments in the line segment are posted on the poster. The purpose of the cover function is to paste a poster on the wall where there is no poster, and to consider whether the current poster can be pasted.
  4. The purpose of the push_up function is to pass the information of the poster up, because it is possible that the left and right line segments of a line segment are covered by two different posters.
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;

int n;
const int MAXN = 10005;

int l[MAXN], r[MAXN];

set<int> st;
int begins[MAXN*2]; /* the begining point of each segment */
int M = 0; /* segments */
int tree[MAXN*4]; /* for each segment i, tree[i] for whether it is covered by a poster */

void push_up(int root)
{
    if (tree[2*root+1] && tree[2*root+2])
        tree[root] = 1;
}

/*
 * k - the index of the post
 * Attention: reset ok before calling this function!!
 */
int ok;
void cover(int root, int L, int R, int LL, int RR)
{
    // printf("calling cover(root=%d, L=%d, R=%d)\n", root, L, R);

    /* important! */
    if (tree[root] == 1)
        return ;

    if (L == LL && R == RR) {
        /* important! */
        if (tree[root] == 0) {
            ok = 1;
            tree[root] = 1;
        }
        return ;
    }

    int mid = (L + R) / 2;
    if (RR <= mid)
        cover(root*2+1, L, mid, LL, RR);
    else if (LL >= mid+1)
        cover(root*2+2, mid+1, R, LL, RR);
    else {
        cover(root*2+1, L, mid, LL, mid);
        cover(root*2+2, mid+1, R, mid+1, RR);
    }

    /* important! */
    push_up(root); 
}

void ini()
{
    st.clear();
    memset(begins, 0, sizeof(begins));
    memset(tree, 0, sizeof(tree));
    M = 0;
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        ini();
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d %d", &l[i], &r[i]);
            st.insert(l[i]);
            st.insert(r[i]+1);
        }
        for (int e : st)
            begins[M++] = e;
        
        --M; // segments = points - 1

        int ans = 0;
        for (int i = n; i >= 1; --i) {
            int L = lower_bound(begins, begins+M, l[i]) - begins;
            int R = lower_bound(begins, begins+M, r[i]+1) - begins - 1;

            ok = 0;
            cover(0, 0, M-1, L, R);
            ans += ok;
        }

        printf("%d\n", ans);
    }
    
    system("pause");
    return 0;
}

 

Guess you like

Origin blog.csdn.net/w112348/article/details/109043977