zoukankan      html  css  js  c++  java
  • bzoj1513

    二维线段树

    听说二维线段树不能下传标记?

    就是裸的二维线段树,由于每次高度只能增加,所以我们就可以标记永久化

    每个线段树里有两个数组,mx和mark,每次修改路径上所有mx都要修改,mark是区间的精确覆盖修改

    每次查询把路径上所有mark取max,然后和精确覆盖区间mx取max

    为什么这样做呢?我们能不能只用一个数组?当然不行,如果我们只用mark,那么假设我们更新区间[1,4],然后查询区间[1,5],那么答案明显不对,如果我们只用mx,那么我们更新[1,1],查询[2,2],那么我们的答案被[1,1]更新了,也是不对。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 3010;
    int n, m, t;
    struct Segment_Tree_X {
        int mx[N], mark[N];
        void update(int l, int r, int x, int a, int b, int tmp)
        {
            if(l > b || r < a) return;
            mx[x] = max(mx[x], tmp);
            if(l >= a && r <= b) 
            {
                mark[x] = max(mark[x], tmp);
                return;
            }
            int mid = (l + r) >> 1;
            update(l, mid, x << 1, a, b, tmp);
            update(mid + 1, r, x << 1 | 1, a, b, tmp);
        }
        int query(int l, int r, int x, int a, int b)
        {
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return mx[x];
            int mid = (l + r) >> 1;
            return max(mark[x], max(query(l, mid, x << 1, a, b), query(mid + 1, r, x << 1 | 1, a, b)));
        }
    };
    struct Segment_Tree_Y {
        Segment_Tree_X mx[N], mark[N];
        void update(int l, int r, int x, int a, int b, int y_l, int y_r, int tmp)
        {
            if(l > b || r < a) return;
            mx[x].update(1, m, 1, y_l, y_r, tmp);
            if(l >= a && r <= b)
            {
                mark[x].update(1, m, 1, y_l, y_r, tmp);
                return;
            }
            int mid = (l + r) >> 1;
            update(l, mid, x << 1, a, b, y_l, y_r, tmp);
            update(mid + 1, r, x << 1 | 1, a, b, y_l, y_r, tmp);
        }
        int query(int l, int r, int x, int a, int b, int y_l, int y_r)
        {
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return mx[x].query(1, m, 1, y_l, y_r);
            int mid = (l + r) >> 1;
            return max(mark[x].query(1, m, 1, y_l, y_r), max(query(l, mid, x << 1, a, b, y_l, y_r), query(mid + 1, r, x << 1 | 1, a, b, y_l, y_r)));
        }
    } T;
    int main()
    {
        scanf("%d%d%d", &n, &m, &t);
        while(t --)
        {
            int d, s, w, x, y, tmp;
            scanf("%d%d%d%d%d", &d, &s, &w, &x, &y);
            ++ x;
            ++ y;
            tmp = T.query(1, n, 1, x, x + d - 1, y, y + s - 1);
            T.update(1, n, 1, x, x + d - 1, y, y + s - 1, w + tmp);
        }
        printf("%d
    ", T.query(1, n, 1, 1, n, 1, m));
        return 0;
    }
    View Code
  • 相关阅读:
    Membership provider Role provider 机制详解
    android Toast大全(五种情形)建立属于你自己的Toast
    android:scaleType属性
    Android接收短信同时获取短信内容
    JAVA三大框架的各自作用
    Android短信监听器
    ImageView / ImageButton 图片太大或者太小解决方法
    Android LayoutInflater详解
    Android开发之Intent.Action
    Android实现短信监听并且转发到指定的手机号,转发后不留痕
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7470639.html
Copyright © 2011-2022 走看看