http://acm.hdu.edu.cn/showproblem.php?pid=4819

题意:给出一个矩阵,然后q个询问,每个询问有a,b,c,代表(a,b)这个点上下左右c/2的矩形区域内的(最大值+最小值)/2是多少,并且将(a,b)的值替换成这个答案。

思路:很久以前被暴力跑过去的一道题,今天怎么交也过不去。。。果然是人品爆发了。

学了一下树套树,一开始觉得挺容易理解,但是后面PushUp那里挺难懂的(对我来说)。

我的理解:

对于每个线段树的结点开一棵线段树,即tree[x][y],x代表的是行的信息,y代表的是列的信息。

觉得PushUp难懂的原因是不知道行上的非叶子结点和列上的非叶子结点是怎么更新的。

 void PushUp1(int x, int y) {
tree[x][y].small = min(tree[x<<][y].small, tree[x<<|][y].small);
tree[x][y].big = max(tree[x<<][y].big, tree[x<<|][y].big);
} void PushUp2(int x, int y) {
tree[x][y].small = min(tree[x][y<<].small, tree[x][y<<|].small);
tree[x][y].big = max(tree[x][y<<].big, tree[x][y<<|].big);
} void Update1(int x, int leaf, int rt, int l, int r, int id, int val) {
if(l == r) {
if(leaf) { tree[x][rt].small = tree[x][rt].big = val; return ; }
PushUp1(x, rt); // 列相同的时候并且行不是叶子结点的时候去更新行的线段树的状态
return ;
}
int m = (l + r) >> ;
if(id <= m) Update1(x, leaf, lson, id, val);
else Update1(x, leaf, rson, id, val);
PushUp2(x, rt);
} void Update2(int rt, int l, int r, int xx, int yy, int val) {
if(l == r) {
Update1(rt, , , , n, yy, val);
return ;
}
int m = (l + r) >> ;
if(xx <= m) Update2(lson, xx, yy, val);
else Update2(rson, xx, yy, val);
Update1(rt, , , , n, yy, val);
}

首先看Update2,这是更新行的线段树信息,和普通线段树一样,只不过是普通的PushUp改成了Update1,插入操作改成了Update1,因此理解Update1就好了。

对于既是列的叶子结点又是行的叶子结点的结点,是对应于矩阵一个点的结点,因此对其赋值修改。

对于是列的叶子结点但是不是行的叶子结点的结点,我们将其行的信息像平时维护一维线段树一样,将行的信息PushUp。

对于不是列的叶子结点的结点,它可以储存列的区间信息,因此将列的信息PushUp。

那么像我之前的疑问,即不是列的叶子结点又不是行的叶子结点的信息在哪里维护。。。

注意原本的PushUp操作变成了Update1,即对于每个行结点,都会去更新对应的那棵线段树,而且是从底向上,因此信息都会被更新。

还优化了一下一开始的读入插入,用类似于Update的Build函数,可以在Build的时候行为叶子列为叶子的时候读入,这样操作为O(n^2)的复杂度,普通的Update插入需要O(n^2 logn^2),跑之后快了一倍的时间。

下面是所有代码:

 #include <bits/stdc++.h>
using namespace std;
#define N 800
#define INF 1000000007
#define lson rt<<1, l, m
#define rson rt<<1|1, m + 1, r
struct node {
int small, big;
} tree[N<<][N<<];
int big, small, n; void PushUp1(int x, int y) {
tree[x][y].small = min(tree[x<<][y].small, tree[x<<|][y].small);
tree[x][y].big = max(tree[x<<][y].big, tree[x<<|][y].big);
} void PushUp2(int x, int y) {
tree[x][y].small = min(tree[x][y<<].small, tree[x][y<<|].small);
tree[x][y].big = max(tree[x][y<<].big, tree[x][y<<|].big);
} void Build1(int x, int leaf, int rt, int l, int r) {
if(l == r) {
if(leaf) { scanf("%d", &tree[x][rt].big), tree[x][rt].small = tree[x][rt].big; return ; }
PushUp1(x, rt); return ;
}
int m = (l + r) >> ;
Build1(x, leaf, lson); Build1(x, leaf, rson);
PushUp2(x, rt);
} void Build2(int rt, int l, int r) {
if(l == r) { Build1(rt, , , , n); return ; }
int m = (l + r) >> ;
Build2(lson); Build2(rson);
Build1(rt, , , , n);
} void Query1(int x, int rt, int l, int r, int y1, int y2) {
if(y1 <= l && r <= y2) {
big = max(big, tree[x][rt].big);
small = min(small, tree[x][rt].small);
return ;
}
int m = (l + r) >> ;
if(y1 <= m) Query1(x, lson, y1, y2);
if(m < y2) Query1(x, rson, y1, y2);
} void Query2(int rt, int l, int r, int x1, int x2, int y1, int y2) {
if(x1 <= l && r <= x2) {
Query1(rt, , , n, y1, y2);
return ;
}
int m = (l + r) >> ;
if(x1 <= m) Query2(lson, x1, x2, y1, y2);
if(m < x2) Query2(rson, x1, x2, y1, y2);
} void Update1(int x, int leaf, int rt, int l, int r, int id, int val) {
if(l == r) {
if(leaf) { tree[x][rt].small = tree[x][rt].big = val; return ; }
PushUp1(x, rt); // 列相同的时候并且行不是叶子结点的时候去更新行的线段树的状态
return ;
}
int m = (l + r) >> ;
if(id <= m) Update1(x, leaf, lson, id, val);
else Update1(x, leaf, rson, id, val);
PushUp2(x, rt);
} void Update2(int rt, int l, int r, int xx, int yy, int val) {
if(l == r) {
Update1(rt, , , , n, yy, val);
return ;
}
int m = (l + r) >> ;
if(xx <= m) Update2(lson, xx, yy, val);
else Update2(rson, xx, yy, val);
Update1(rt, , , , n, yy, val);
} int main() {
int t; scanf("%d", &t);
for(int cas = ; cas <= t; cas++) {
scanf("%d", &n);
Build2(, , n);
int q; scanf("%d", &q);
printf("Case #%d:\n", cas);
while(q--) {
int a, b, c; scanf("%d%d%d", &a, &b, &c);
int x1 = max(, a - c / ), x2 = min(n, a + c / );
int y1 = max(, b - c / ), y2 = min(n, b + c / );
big = -INF, small = INF;
Query2(, , n, x1, x2, y1, y2);
int now = (big + small) / ;
printf("%d\n", now);
Update2(, , n, a, b, now);
}
}
return ;
}

HDU 4819:Mosaic(线段树套线段树)的更多相关文章

  1. HDU 4819 Mosaic (二维线段树)

    Mosaic Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)Total S ...

  2. HDU 4819 Mosaic (二维线段树&区间最值)题解

    思路: 二维线段树模板题,马克一下,以后当模板用 代码: #include<cstdio> #include<cmath> #include<cstring> #i ...

  3. HDU 4819 Mosaic 【二维线段树】

    题目大意:给你一个n*n的矩阵,每次找到一个点(x,y)周围l*l的子矩阵中的最大值a和最小值b,将(x,y)更新为(a+b)/2 思路:裸的二维线段树 #include<iostream> ...

  4. HDU 4819 Mosaic(13年长春现场 二维线段树)

    HDU 4819 Mosaic 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4819 题意:给定一个n*n的矩阵,每次给定一个子矩阵区域(x,y,l) ...

  5. hdu-4819-线段树套线段树

    http://acm.hdu.edu.cn/showproblem.php?pid=4819 给出一个N*N的矩阵,每次询问一个m*m的子矩阵里的floor((maxv+minv)/2)并把中间的元素 ...

  6. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  7. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  8. ZJOI 2017 树状数组(线段树套线段树)

    题意 http://uoj.ac/problem/291 思路 不难发现,九条カレン醬所写的树状数组,在查询区间 \([1,r]\) 的时候,其实在查询后缀 \([r,n]\) :在查询 \([l,r ...

  9. BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)

    题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...

  10. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

随机推荐

  1. WPF listview item mouse enter/over popup

    This is because the routing strategy of the Loaded event is Direct, which means that the routed even ...

  2. jquery表单过滤器

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  3. 使用sklearn构建含有标量属性的决策树

    网络上使用sklearn生成决策树的资料很多,这里主要说明遇见标量数据的处理. 经查验参考资料,sklearn并非使用了课上以及书上讲的ID3算法,而是选择了CART,该算法生成二叉树:scikit- ...

  4. iText类库再pdf中显示中文字体

    using iTextSharp.text; using System; using System.Collections.Generic; using System.IO; using System ...

  5. SQL Server 2017 SELECT…INTO 创建的新表指定到文件组

    原文:SQL Server 2017 SELECT-INTO 创建的新表指定到文件组 SELECT-INTO 在 SQL Server 中也是常见的一个功能,过去用此方法创建的新表只能存储到默认的文件 ...

  6. /etc/passwd和/etc/group文件详解

    用户管理 想要知道, 系统中有哪些用户, 可以查看这个文件: /etc/passwd root:x:::root:/root:/bin/bash bin:x:::bin:/bin:/sbin/nolo ...

  7. KmdKit4D 0.01正式版发布了(0.02版已放出)(Delphi做驱动)

    此版本较0.01预览版已经有了脱胎换骨的变化,主要表现在以下几个方面:    1.对程序的结构进行了调整,将原来的ntutils.dcu分成fcall.dcu.halfcall.dcu和macros. ...

  8. qtextedit中的光标问题(通过调用repaint去掉Focus的阴影)

    [问题]两个textedit,取名为view0,view1.实现view0输入固定的字符个数后,用setFocus切换聚焦到view1,但是切换完了之后view0还会保留光标残影,出现两个文本框中都有 ...

  9. dpkg:处理 xxx (--configure)时出错解决方案

    出现问题如下: 正在设置 nfs-common (1:1.2.2-4ubuntu5) ... dpkg:处理 nfs-common (--configure)时出错:  子进程 已安装 post-in ...

  10. poi 操作Excel 以及大数据量导出

    maven 依赖 (版本必须一致,否则使用SXSSFworkbook 时程序会报错) <dependency> <groupId>org.apache.poi</grou ...