HDU 4819 Mosaic(二维线段树区间查询+单点更新模板)
来源:互联网 发布:bp神经网络算法 matlab 编辑:程序博客网 时间:2024/05/21 09:17
The God of sheep decides to pixelate some pictures (i.e., change them into pictures with mosaic). Here's how he is gonna make it: for each picture, he divides the picture into n x n cells, where each cell is assigned a color value. Then he chooses a cell, and checks the color values in the L x L region whose center is at this specific cell. Assuming the maximum and minimum color values in the region is A and B respectively, he will replace the color value in the chosen cell with floor((A + B) / 2).
Can you help the God of sheep?
Can you help the God of sheep?
Each test case begins with an integer n (5 < n < 800). Then the following n rows describe the picture to pixelate, where each row has n integers representing the original color values. The j-th integer in the i-th row is the color value of cell (i, j) of the picture. Color values are nonnegative integers and will not exceed 1,000,000,000 (10^9).
After the description of the picture, there is an integer Q (Q ≤ 100000 (10^5)), indicating the number of mosaics.
Then Q actions follow: the i-th row gives the i-th replacement made by the God of sheep: xi, yi, Li (1 ≤ xi, yi ≤ n, 1 ≤ Li < 10000, Li is odd). This means the God of sheep will change the color value in (xi, yi) (located at row xi and column yi) according to the Li x Li region as described above. For example, an query (2, 3, 3) means changing the color value of the cell at the second row and the third column according to region (1, 2) (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4). Notice that if the region is not entirely inside the picture, only cells that are both in the region and the picture are considered.
Note that the God of sheep will do the replacement one by one in the order given in the input.��
For each action, print the new color value of the updated cell.
131 2 34 5 67 8 952 2 13 2 31 1 31 2 32 2 3
Case #1:56346
题解:
题意:
就是给你一个n*n的矩阵,每次询问一个点的坐标,和l,以该点坐标为中心搞一个长宽都为l的正方形矩阵,求该矩阵的最大值和最小值,然后修改该点的值为最大值和最小值的平均值
之前只做过二维的树状数组,二维线段树真不会啊,我直接搜了个博客,看懂了以后直接复制了他的博客,因为原文注释比较少,所以我就加上了我的注释,也是我的理解。。。真想知道世界上第一个想出二维线段树的人是这么写出来的
原博客博主:http://blog.csdn.net/htt_h/article/details/44944039
ps:
强迫症的我删掉了他的所有空格,把位运算改成了加和乘运算,然后代码对齐了。。。。
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 801#define inf 0x3f3f3f3fint maxi[maxn*3][maxn*3];int mini[maxn*3][maxn*3];int n;int val;//修改的值int x,y;//修改点,设为全局变量就不用传到参数里int x1,x2,y1,y2;//查询的区间int crx;//只表示一行的外层线段树节点编号int cmax,cmin;//记录查询区间的最大值最小值void buildy(int rx,int ry,int l,int r)//构造行{ if(l==r)//如果当前行长度为1 { if(rx==crx)//当前列的长度也为1,则表示坐标点,直接赋值 { scanf("%d",&mini[rx][ry]); maxi[rx][ry]=mini[rx][ry]; } else//区间列的长度不为1,则为一列的最值,由外层的那列左右子树的最值来pushup { int lrx=rx*2,rrx=rx*2+1; maxi[rx][ry]=max(maxi[lrx][ry],maxi[rrx][ry]); mini[rx][ry]=min(mini[lrx][ry],mini[rrx][ry]); } return; } int m =(l+r)/2; int lc=ry*2,rc=ry*2+1; buildy(rx,lc,l,m);//行长度不为1继续分下去 buildy(rx,rc,m+1,r); maxi[rx][ry]=max(maxi[rx][lc],maxi[rx][rc]);//区间行的长度不为1,则为一行的最值,用行的左右子树来更新区间 mini[rx][ry]=min(mini[rx][lc],mini[rx][rc]);}void buildx(int rx,int l,int r)//构造列{ int m =(l+r)/2; if(r>l)//如果不是一列,就继续二分建树 { buildx(rx*2,l,m); buildx(rx*2+1,m+1,r); } if(l==r){crx=rx;x=l;}//如果列的长度为1,就记录当前节点列的标号,用于在子树中判断是否为一列 buildy(rx,1,1,n);//构造行}void updatey(int rx,int ry,int l,int r)//更新行{ if(l==r)//行的长度为1 { if(rx==crx)//列的长度为1,代表是要更新的点 maxi[rx][ry]=mini[rx][ry]=val; else{//否则继续划分列,直到查到了该点的列为止 int lrx=rx*2,rrx=rx*2+1; maxi[rx][ry]=max(maxi[lrx][ry],maxi[rrx][ry]);//这时列的长度不为1,为一列的最值,由列的左右子树更新 mini[rx][ry]=min(mini[lrx][ry],mini[rrx][ry]); } return; } int m=(l+r)/2; int lc=ry*2,rc=ry*2+1; if(y<=m)//查找该行 updatey(rx,lc,l,m); else updatey(rx,rc,m+1,r); maxi[rx][ry]=max(maxi[rx][lc],maxi[rx][rc]);//这时行的长度不为1就是由行的左右子树更新 mini[rx][ry]=min(mini[rx][lc],mini[rx][rc]);}void updatex(int rx, int l, int r)//更新列{ int m=(l+r)/2; int lc=rx*2,rc=rx*2+1; if(r>l)//列的长度大于1就继续分 { if(x<=m) updatex(lc,l,m); else updatex(rc,m+1,r); } if(l==r) crx=rx; updatey(rx,1,1,n);//查找到该列就更新行}void qy(int rx,int ry,int l,int r)//查询行{ if(y1<=l&&y2>=r)//询问到了询问的子区间 { cmin=min(cmin,mini[rx][ry]); cmax=max(cmax,maxi[rx][ry]); return; } int m=(l+r)/2; int lc=ry*2,rc=ry*2+1; if(y1<=m) qy(rx,lc,l,m); if(y2>m) qy(rx,rc,m+1,r);}void qx(int rx,int l,int r)//询问列{ if(x1<=l&&x2>=r)//询问到了列的子区间,询问行 { qy(rx,1,1,n); return; } int m =(l+r)/2; int lc=rx*2,rc=rx*2+1; if(x1<=m) qx(lc,l,m); if(x2>m) qx(rc,m+1,r);}int main(){ int t,cnt=1; scanf("%d",&t); while(t--) { memset(maxi,-inf,sizeof(maxi)); memset(mini,inf,sizeof(mini)); printf("Case #%d:\n",cnt++); scanf("%d",&n); buildx(1,1,n); int l; int q; scanf("%d",&q); while(q--) { scanf("%d%d%d",&x,&y,&l); l/=2; x1=max(1,x-l);x2=min(n,x+l); y1=max(1,y-l);y2=min(n,y+l); cmax=-inf,cmin=inf;qx(1,1,n);//初始化最大最小为负无穷和正无穷 val=(cmin+cmax)/2; printf("%d\n",val); crx=-1;updatex(1,1,n); } } return 0;}
阅读全文
0 0
- HDU 4819 Mosaic(二维线段树区间查询+单点更新模板)
- HDU 4819 Mosaic(二维线段树单点更新+区间查询+自己的写法模板)
- hdoj 4819 Mosaic 【二维线段树 单点更新 区间查询】
- HDU 4819 Mosaic(二维线段树+单点更新)
- HDU 4819:单点更新,区间查询的二维线段树
- 【HDU 4819】Mosaic 二维线段树模板
- HDU 4819 Mosaic(二维线段树模板)
- HDU1823 Luck and Love(二维线段树单点更新+区间查询+模板)
- Luck and Love(二维线段树单点更新+区间查询+模板)
- HDU 4819 Mosaic (二维线段树)
- HDU 4819 Mosaic(二维线段树)
- 二维线段树(Mosaic,hdu 4819)
- HDU 4819 Mosaic (二维线段树)
- HDU 4819 Mosaic (二维线段树)
- hdu 4819 二维线段树,单点修改区间查询
- Hdu4819 Mosaic 二维线段树维护区间最值+单点更新
- hdu 4046 Panda (线段树 单点更新 区间查询)
- HDU 1754 (线段树+单点更新+区间查询)
- iOS开发中点击UITabBarItem弹出一个控制器(如常见未登录用户点击购物车弹出登录页面的效果)
- 利用java实现的一个发送手机短信的小例子
- SpringSecurity【用户+权限的数据库持久化】
- faster rcnn 训练
- sbc(四)应用限流
- HDU 4819 Mosaic(二维线段树区间查询+单点更新模板)
- 弹出框 点击确定与取消时,跳转页面
- PHP Error 和 Logging 函数
- js打印div指定区域内容
- Something about cpu and memory hot plug on kvm
- DigitalOcean租VPS,配置过程
- 求最大子矩阵的和、求最大子数组的和
- 深度优先搜索(DFS)
- PHP 5 Date/Time 函数