• HDU4819 Mosaic【树套树】


    LINK

    题目大意

    给你一个(n*n)矩阵,每个点有初始权值

    q次询问每次把一个矩形的中心节点变成这个矩形中最大值和最小值的平均数

    思路

    很显然的树套树啊

    就是一开始傻逼了没想到怎么去维护这个东西

    其实很简单

    对于每个内层树,如果属于外层树的叶子节点,那么可以直接暴力更新,复杂度(O(log(n)))

    void modify_y(int t, int l, int r, int pos, int vl, int id) {
      if (l == r) {
        minv[id][t] = vl;
        maxv[id][t] = vl;
        return;
      }
      int mid = (l + r) >> 1;
      if (pos <= mid) modify_y(LD(t), l, mid, pos, vl, id);
      else modify_y(RD(t), mid + 1, r, pos, vl, id);
      pushup(t, id);
    }
    

    然后如果要更新不是叶子节点外层树对应的内层树怎么办?

    考虑从外层树的儿子节点合并对应的信息,只需要修改有影响的一条链,复杂度(O(nlog(n)))

    void update_y(int t, int l, int r, int pos, int id) {
      if (l == r) {
        minv[id][t] = min(minv[LD(id)][t], minv[RD(id)][t]);
        maxv[id][t] = max(maxv[LD(id)][t], maxv[RD(id)][t]);
        return;
      }
      int mid = (l + r) >> 1;
      if (pos <= mid) update_y(LD(t), l, mid, pos, id);
      else update_y(RD(t), mid + 1, r, pos, id);
      pushup(t, id);
    }
    

    内层树的查询就简单而套路了

    pi query_y(int t, int l, int r,int ql, int qr, int id) {
      if (ql <= l && r <= qr) return pi(maxv[id][t], minv[id][t]);
      int mid = (l + r) >> 1;
      if (qr <= mid) return query_y(LD(t), l, mid, ql, qr, id);
      else if (ql > mid) return query_y(RD(t), mid + 1, r, ql, qr, id);
      else {
        pi ansl = query_y(LD(t), l, mid, ql, mid, id);
        pi ansr = query_y(RD(t), mid + 1, r, mid + 1, qr, id);
        return pi(max(ansl.first, ansr.first), min(ansl.second, ansr.second));
      }
    }
    

    外层树修改的时候需要判断一下当前节点是不是叶子,如果是叶子直接更新y

    否则先递归问题再调用(update_y)函数

    void modify_x(int t, int l, int r, int x, int y, int vl) {
      if (l == r) {
        modify_y(1, 1, n, y, vl, t);
        return;
      }
      int mid = (l + r) >> 1;
      if (x <= mid) modify_x(LD(t), l, mid, x, y, vl);
      else modify_x(RD(t), mid + 1, r, x, y, vl);
      update_y(1, 1, n, y, t);
    }
    

    外层树的查询就是如果被查询区间包含调用内层查询,否则递归问题

    pi query_x(int t, int l, int r, int xl, int xr, int yl, int yr) {
      if (xl <= l && r <= xr) return query_y(1, 1, n, yl, yr, t);
      int mid = (l + r) >> 1;
      if (xr <= mid) return query_x(LD(t), l, mid, xl, xr, yl, yr);
      else if (xl > mid) return query_x(RD(t), mid + 1, r, xl, xr, yl, yr);
      else {
        pi ansl = query_x(LD(t), l, mid, xl, mid, yl, yr);
        pi ansr = query_x(RD(t), mid + 1, r, mid + 1, xr, yl, yr);
        return pi(max(ansl.first, ansr.first), min(ansl.second, ansr.second));
      }
    }
    
  • 相关阅读:
    面向对象设计原则之接口隔离原则
    面向对象设计原则之开闭原则
    [OOD]违反里氏替换原则的解决方案
    错误程序
    error: ‘for’ loop initial declarations are only allowed in C99 mode
    函数模板
    查找
    队列类模板
    栈类模板
    单链表的结点类模板
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9867915.html
Copyright © 2020-2023  润新知