POJ 3277 线段树 + 延迟标记

来源:互联网 发布:淘宝黑莓手机是真的吗 编辑:程序博客网 时间:2024/05/29 14:01

本题就是给出一堆矩形,然后让我们算总共的面积,也就是重复的面积只算一次。需要用到线段树,每次输入矩形的左端点和右端点,还有高。我们就把这条线段插进去,线段的高度取较高的那一个。注意到这和普通的线段树不太一样,普通的情况是,当我们插入的线段完全覆盖线段树中的某一条线段时,那条线段的值就被更新成插入的线段的值。但是本题的情况却不太一样,当我们插入的线段完全覆盖线段树的某一条线段时,如果现在的权值大于原有线段的权值,就将其覆盖。但是一定要注意,更新之后的线段树的值并不一定是正确的。

比如我们最先插入(1,5),5。然后打上延迟标记。第二次插入(1,3),7。所以我们就把延迟标记下移。(1,3)和(3,5)都更新成5,然后(1,3)变成7。然后再把(1,5)更新成6。现在假如我们来查询,难道(1,5)的值就是6吗?明显不是,(1,3)区间的权值是7,(3,5)区间的值为5。那么怎么才能查询到正确的结果呢?只需要从根节点,不断的往叶子节点更新就行了。


所以这道题:


1.更新的时候延迟标记下移的规则不是完全覆盖,是取一个区间中的最大值


2.查询的时候,从根节点往叶子节点更新


3.本题线段树叶子节点应该构建成(x,x + 1)的形式,不然会漏掉[m,m + 1]的面积

#include <algorithm>#include <iostream>#include <iterator>#include <sstream>#include <fstream>#include <istream>#include <ostream>#include <complex>#include <cstring>#include <utility>#include <cstdlib>#include <cstdio>#include <vector>#include <string>#include <cctype>#include <ctime>#include <cmath>#include <queue>#include <stack>#include <list>#include <new>#include <set>#include <map>#define lson l, m, k << 1#define rson m, r, k << 1| 1using namespace std;typedef long long int LL;const int INF = 0x3f3f3f3f;const int maxn = 200000 << 2;LL cover[maxn], maxh[maxn], li[maxn], ri[maxn], hi[maxn], x[maxn];void pushdown(int k){    if (cover[k]){        if (maxh[k << 1] < maxh[k]){            maxh[k << 1] = maxh[k];            cover[k << 1] = 1;        }        if (maxh[k << 1 | 1] < maxh[k]){            maxh[k << 1 | 1] = maxh[k];            cover[k << 1 | 1] = 1;        }        cover[k] = 0;    }}void update(int l, int r, int k, int L, int R, int H){    if (L == l && R == r){        if (maxh[k] < H){            maxh[k] = H;            cover[k] = 1;        }        return;    }    pushdown(k);    int m = (l + r) >> 1;    if (R <= m) update(lson, L, R, H);    else if (L >= m) update(rson, L, R, H);    else{        update(lson, L, m, H);        update(rson, m, R, H);    }}LL query(int l, int r, int k){    if (l == r - 1) return maxh[k] * (x[r] - x[l]);    maxh[k << 1] = max(maxh[k], maxh[k << 1]);    maxh[k << 1 | 1] = max(maxh[k], maxh[k << 1 | 1]);    int m = (l + r) >> 1;    return query(lson) + query(rson);}int Binary_Search(int s, int e, int key) {    int left = s, right = e, mid;    while (left <= right) {        mid = (left + right) >> 1;        if (x[mid] >= key)  right = mid - 1;        else left = mid + 1;    }    if (x[left] == key) return left;    return -1;}int main(){    //freopen("1.txt", "r", stdin);    int n;    scanf ("%d", &n);    int nn = 0;    for (LL i = 1; i <= n; i++) {        scanf ("%I64d%I64d%I64d", &li[i], &ri[i], &hi[i]);        x[++nn] = li[i];        x[++nn] = ri[i];    }        memset(maxh, 0, sizeof(maxh));//建树    memset(cover, 0, sizeof(cover));    sort(x + 1, x + nn + 1);//离散化    int len = unique(x + 1, x + nn + 1) - (x + 1);    for (LL i = 1; i <= n; i++) {        LL l = Binary_Search(1, len + 1, li[i]);        LL r = Binary_Search(1, len + 1, ri[i]);        update(1, len, 1, l, r, hi[i]);    }        printf("%I64d\n", query(1, len, 1));    return 0;}




0 0
原创粉丝点击