【UVALive】6709 Mosaic 二维线段树

2024-09-05 15:58

本文主要是介绍【UVALive】6709 Mosaic 二维线段树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门:【UVALive】6709 Mosaic

题目大意:
每次选择矩阵中的一个点,求以他为中心,边长为D(D一定是奇数)的矩阵中的最小值min和最大值max,输出ans =(min+max)/ 2(向下取整)。然后将该点的值修改为ans。

题目分析:
赤果果的二维线段树单点修改、区间查询。
又一次学习了线段树,发现原来所有的更新操作全部放在二维中即可。
很不错,一定要经常看看,温故知新~

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;typedef long long BigInt ;#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define rt o , l , r
#define root 1 , 1 , n
#define lson ls , l , m
#define rson rs , m + 1 , r
#define mid ( ( l + r ) >> 1 )
#define LLRR Lx , Rx , Ly , Ry
#define clear( A , X ) memset ( A , X , sizeof A )const int maxN = 800 ;
const int oo = 0x3f3f3f3f ;int mmax[maxN << 2][maxN << 2] ;
int mmin[maxN << 2][maxN << 2] ;
int minv , maxv ;
int n ;int max ( const int a , const int b ) {if ( a > b ) return a ;return b ;
}int min ( const int a , const int b ) {if ( a < b ) return a ;return b ;
}void PushUp ( int pos , int o ) {mmax[pos][o] = max ( mmax[pos][ls] , mmax[pos][rs] ) ;mmin[pos][o] = min ( mmin[pos][ls] , mmin[pos][rs] ) ;
}void SubBuild ( int ch , int pos , int o , int l , int r ) {mmax[pos][o] = -oo ;mmin[pos][o] =  oo ;if ( l == r ) {if ( !ch ) { scanf ( "%d" , &mmin[pos][o] ) ;mmax[pos][o] = mmin[pos][o] ;}else {mmin[pos][o] = min ( mmin[pos << 1][o] , mmin[pos << 1 | 1][o] ) ;mmax[pos][o] = max ( mmax[pos << 1][o] , mmax[pos << 1 | 1][o] ) ;}return ;}int m = mid ;SubBuild ( ch , pos , lson ) ;SubBuild ( ch , pos , rson ) ;PushUp ( pos , o ) ;
}void Build ( int o , int l , int r ) {if ( l == r ) {SubBuild ( 0 , o , root ) ;return ;}int m = mid ;Build ( lson ) ;Build ( rson ) ;SubBuild ( 1 , o , root ) ;
}void SubUpdate ( int ch , int pos , int y , int v , int o , int l , int r ) {if ( l == r ) {if ( !ch ) mmin[pos][o] = mmax[pos][o] = v ;else {mmin[pos][o] = min ( mmin[pos << 1][o] , mmin[pos << 1 | 1][o] ) ;mmax[pos][o] = max ( mmax[pos << 1][o] , mmax[pos << 1 | 1][o] ) ;}return ;}int m = mid ;if ( y <= m ) SubUpdate ( ch , pos , y , v , lson ) ;else          SubUpdate ( ch , pos , y , v , rson ) ;PushUp ( pos , o ) ;
}void Update ( int x , int y , int v , int o , int l , int r ) {if ( l == r ) {SubUpdate ( 0 , o , y , v , root ) ;return ;}int m = mid ;if ( x <= m ) Update ( x , y , v , lson ) ;else 	      Update ( x , y , v , rson ) ;SubUpdate ( 1 , o , y , v , root ) ;
}void SubQuery ( int L , int R , int pos , int o , int l , int r ) {if ( L <= l && r <= R ) {minv = min ( minv , mmin[pos][o] ) ;maxv = max ( maxv , mmax[pos][o] ) ;return ;}int m = mid ;if ( L <= m ) SubQuery ( L , R , pos , lson ) ;if ( m <  R ) SubQuery ( L , R , pos , rson ) ;
}void Query ( int Lx , int Rx , int Ly , int Ry , int o , int l , int r ) {if ( Lx <= l && r <= Rx ) {SubQuery ( Ly , Ry , o , root ) ;return ;}int m = mid ;if ( Lx <=  m ) Query ( LLRR , lson ) ;if ( m  <  Rx ) Query ( LLRR , rson ) ;
}void work () {int m , w , x , y ;int x1 , x2 , y1 , y2 ;scanf ( "%d" , &n ) ;Build ( root ) ;scanf ( "%d" , &m ) ;while ( m -- ) {scanf ( "%d%d%d" , &x , &y , &w ) ;w >>= 1 ;x1 = max ( 1 , x - w ) ;x2 = min ( n , x + w ) ;y1 = max ( 1 , y - w ) ;y2 = min ( n , y + w ) ;minv = oo , maxv = -oo ;Query ( x1 , x2 , y1 , y2 , root ) ;int v = ( minv + maxv ) >> 1 ;printf ( "%d\n" , v ) ;Update ( x , y , v , root ) ;}
}int main () {int T , cas ;for ( scanf ( "%d" , &T ) , cas = 1 ; cas <= T ; ++ cas ) {printf ( "Case #%d:\n" , cas ) ;work () ;}return 0 ;
}

这篇关于【UVALive】6709 Mosaic 二维线段树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139414

相关文章

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后

HDU4737线段树

题目大意:给定一系列数,F(i,j)表示对从ai到aj连续求或运算,(i<=j)求F(i,j)<=m的总数。 const int Max_N = 100008 ;int sum[Max_N<<2] , x[Max_N] ;int n , m ;void push_up(int t){sum[t] = sum[t<<1] | sum[t<<1|1] ;}void upd

HDU 2159 二维完全背包

FATE 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能