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. 【iOS发展-49】的插件-插件该文档的凝视VVDocumenter安装与使用

    文件凝视是/**   */.快捷键///. 但是,这需要安装插件.VVDocumenter. 下载链接:https://github.com/onevcat/VVDocumenter-Xcode (1 ...

  2. 精装友好联络算法实现借壳和RI

    精装友好联络会 注册算法分析: 1.  许可证由三部分组成. 2. 的登记号的第一部分是顺序编号0x6d模 3. 登记代码的第二部分: 先将订单号与0XB25F1异或,将异或后的结果转换成十进制字符串 ...

  3. js 动态生成button 并设置click事件

    <div id="MyDiv"></div> <script> function AddButton() { var MyDiv =docume ...

  4. WPF 控件的内容属性

    WPF的内容属性不应定都是content, 例如TextBlock的内容属性是Text Panel的内容属性是Children ListBox的内容属性是Items

  5. 【Repo】推送一个已有的代码到新的 gerrit 服务器

    1.指定项目代码库中迭代列出全部ProductList(.git)到pro.log文件中 repo forall -c 'echo $REPO_PROJECT' | tee pro.log 命令解读: ...

  6. Win8Metro(C#)数字图像处理--2.14Prewitt 边缘检测

    原文:Win8Metro(C#)数字图像处理--2.14Prewitt 边缘检测  [函数名称] 图像Prewitt边缘检测函数PrewittEdgeProcess(WriteableBitmap ...

  7. 把BitmapSource图片数据保存到文件

    实现函数: /// <summary> /// 保存图片到文件 /// </summary> /// <param name="image">图 ...

  8. Database time zone version is 18. It is older than current release time zone version 26

    [oracle@raca1 12.2.0]$ sqlplus / as sysdba SQL Production :: Copyright (c) , , Oracle. All rights re ...

  9. 开启Qt Lite Project

    发布: http://blog.qt.io/blog/2017/01/23/qt-5-8-released/ 说法一:Qt Lite” is not a tool, but a concept tha ...

  10. HTML5 拖放并删除效果的简单实现

    Html5 支持元素drag drop的功能需求,以后实现这类效果会简单很多.. 详细的文档说明在这里 代码如下所示: