HDU4819 Mosaic

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

Problem Description

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?

Input

The first line contains an integer T (T ≤ 5) indicating
the number of test cases. Then T test cases follow.

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.

Output

For each test case, print a line "Case #t:"(without
quotes, t means the index of the test case) at the beginning.

For each
action, print the new color value of the updated cell.

Sample Input

1
3
1 2 3
4 5 6
7 8 9
5
2 2 1
3 2 3
1 1 3
1 2 3
2 2 3

Sample Output

Case #1:
5
6
3
4
6

正解:二维线段树

解题报告:

  又调了一个晚上的题目…

  (每晚留一道题目调不完的debuff...)

  二维线段树相当于是维护了一个矩阵,不妨叫做主线段树和副线段树,那么主线段树上的每个节点都存了一棵副线段树(可以动态开节点呀),那么就没有区别了…

  只是要注意一点,modify了之后显然不能直接merge两个子树,复杂度是线性的...

  直接查询两个子树的这一位,取max/min然后在子树上直接modify即可。

  

//It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
using namespace std;
typedef long long LL;
const int MAXN = 811;
const int MAXM = 5000011;
int n,m,ju[MAXN][MAXN],X[2],Y[2],cnt,rt,ans,CC;
struct node{ int l,r,ls,rs,maxl,minl,tree; }a[MAXM];
inline int getint(){
    int w=0,q=0; char c=getchar(); while((c<‘0‘||c>‘9‘) && c!=‘-‘) c=getchar();
    if(c==‘-‘) q=1,c=getchar(); while (c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w;
}

namespace Seg_tree{
	inline void build(int &k,int l,int r,int bel){
		k=++cnt; a[k].l=l; a[k].r=r; if(l==r) { a[k].minl=a[k].maxl=ju[l][bel]; return ; }
		int mid=(l+r)>>1; build(a[k].ls,l,mid,bel); build(a[k].rs,mid+1,r,bel);
		a[k].minl=min(a[a[k].ls].minl,a[a[k].rs].minl); a[k].maxl=max(a[a[k].ls].maxl,a[a[k].rs].maxl);
	}

	inline int query_min(int k,int l,int r){
		if(Y[0]<=l && r<=Y[1]) return a[k].minl;
		int mid=(l+r)>>1;
		if(Y[0]>mid) return query_min(a[k].rs,mid+1,r);
		else if(Y[1]<=mid) return query_min(a[k].ls,l,mid);
		else return min(query_min(a[k].ls,l,mid),query_min(a[k].rs,mid+1,r));
	}

	inline int query_max(int k,int l,int r){
		if(Y[0]<=l && r<=Y[1]) return a[k].maxl;
		int mid=(l+r)>>1;
		if(Y[0]>mid) return query_max(a[k].rs,mid+1,r);
		else if(Y[1]<=mid) return query_max(a[k].ls,l,mid);
		else return max(query_max(a[k].ls,l,mid),query_max(a[k].rs,mid+1,r));
	}

	inline void modify(int k,int l,int r,int y){
		if(l==r) { a[k].minl=a[k].maxl=ans; return ; }
		int mid=(l+r)>>1;
		if(y<=mid) modify(a[k].ls,l,mid,y); else modify(a[k].rs,mid+1,r,y);
		a[k].minl=min(a[a[k].ls].minl,a[a[k].rs].minl); a[k].maxl=max(a[a[k].ls].maxl,a[a[k].rs].maxl);
	}

	inline void update_min(int k,int l,int r,int y){
		if(l==r) { a[k].minl=CC; return ; }
		int mid=(l+r)>>1;
		if(y<=mid) update_min(a[k].ls,l,mid,y); else update_min(a[k].rs,mid+1,r,y);
		a[k].minl=min(a[a[k].ls].minl,a[a[k].rs].minl);
	}

	inline void update_max(int k,int l,int r,int y){
		if(l==r) { a[k].maxl=CC; return ; }
		int mid=(l+r)>>1;
		if(y<=mid) update_max(a[k].ls,l,mid,y); else update_max(a[k].rs,mid+1,r,y);
		a[k].maxl=max(a[a[k].ls].maxl,a[a[k].rs].maxl);
	}
}

inline void merge(int &k,node q,node qq){
	if(!k) k=++cnt; a[k].maxl=max(q.maxl,qq.maxl); a[k].minl=min(q.minl,qq.minl);
	a[k].l=q.l; a[k].r=q.r; if(q.l==q.r) return ;
	merge(a[k].ls,a[q.ls],a[qq.ls]);
	merge(a[k].rs,a[q.rs],a[qq.rs]);
}

inline void build(int &k,int l,int r){
	k=++cnt; a[k].l=l; a[k].r=r;
	if(l==r) {
		Seg_tree::build(a[k].tree,1,n,l);
		return;
	}
	int mid=(l+r)>>1; build(a[k].ls,l,mid); build(a[k].rs,mid+1,r);
	merge(a[k].tree,a[ a[a[k].ls].tree ],a[ a[a[k].rs].tree ]);
}

inline int query_min(int k,int l,int r){
	if(X[0]<=l && r<=X[1]) return Seg_tree::query_min(a[k].tree,1,n);
	int mid=(l+r)>>1;
	if(X[0]>mid) return query_min(a[k].rs,mid+1,r);
	else if(X[1]<=mid) return query_min(a[k].ls,l,mid);
	else return min(query_min(a[k].ls,l,mid),query_min(a[k].rs,mid+1,r));
}

inline int query_max(int k,int l,int r){
	if(X[0]<=l && r<=X[1]) return Seg_tree::query_max(a[k].tree,1,n);
	int mid=(l+r)>>1;
	if(X[0]>mid) return query_max(a[k].rs,mid+1,r);
	else if(X[1]<=mid) return query_max(a[k].ls,l,mid);
	else return max(query_max(a[k].ls,l,mid),query_max(a[k].rs,mid+1,r));
}

inline void modify(int k,int l,int r,int x,int y){
	if(l==r) { Seg_tree::modify(a[k].tree,1,n,y); return ; }
	int mid=(l+r)>>1;
	if(x<=mid) modify(a[k].ls,l,mid,x,y);
	else modify(a[k].rs,mid+1,r,x,y);

	int lc=a[k].ls,rc=a[k].rs;
	int lmin=Seg_tree::query_min(a[lc].tree,a[a[lc].tree].l,a[a[lc].tree].r);
	int rmin=Seg_tree::query_min(a[rc].tree,a[a[rc].tree].l,a[a[rc].tree].r);
	CC=min(lmin,rmin); Seg_tree::update_min(a[k].tree,a[a[k].tree].l,a[a[k].tree].r,y);

	int lmax=Seg_tree::query_max(a[lc].tree,a[a[lc].tree].l,a[a[lc].tree].r);
	int rmax=Seg_tree::query_max(a[rc].tree,a[a[rc].tree].l,a[a[rc].tree].r);
	CC=max(lmax,rmax); Seg_tree::update_max(a[k].tree,a[a[k].tree].l,a[a[k].tree].r,y);
	//merge(a[k].tree,a[ a[a[k].ls].tree ],a[ a[a[k].rs].tree ]);
}

inline void work(){
	int T=getint();
	for(int Case=1;Case<=T;Case++) {
		printf("Case #%d:\n",Case);	n=getint(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ju[i][j]=getint();
		for(int i=1;i<=cnt;i++) a[i].tree=a[i].ls=a[i].rs=0; cnt=0; rt=0;
		build(rt,1,n); m=getint(); int x,y,z,da,xiao;
		while(m--) {
			y=getint(); x=getint(); z=getint();	z>>=1;
			X[0]=max(x-z,1); X[1]=min(x+z,n);
			Y[0]=max(y-z,1); Y[1]=min(y+z,n);
			da=query_max(rt,1,n);
			xiao=query_min(rt,1,n);
			ans=(da+xiao)>>1; printf("%d\n",ans);
			Y[0]=Y[1]=y;
			modify(rt,1,n,x,y);
		}
	}

}

int main()
{
    work();
    return 0;
}

  

时间: 2024-11-25 11:51:15

HDU4819 Mosaic的相关文章

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;

URAL Mosaic(并查集)(欧拉回路)

Mosaic Time limit: 0.25 secondMemory limit: 64 MB There's no doubt that one of the most important and crucial things to do in this world is to bring up children. May be, if you study properly and reach good results at the competition you'll get a pos

HDU 4819 Mosaic (二维线段树)

Problem Description 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

UnityShader实例11:屏幕特效之马赛克(Mosaic)材质

马赛克(Mosaic)材质 概述 马赛克(Mosaic),估计是大伙平时很常见最讨厌的图片处理手段,嘿嘿,没错我说的就是"打码".好了,正经点,马赛克指现行广为使用的一种图像(视频)处理手段,此手段将影像特定区域的色阶细节劣化并造成色块打乱的效果,因为这种模糊看上去有一个个的小格子组成,便形象的称这种画面为马赛克.其目的通常是让图像大规模的降低图像()视频分辨率,而让图像(视频)的一些细节隐藏起来,使之无法辨认,一般用来保护隐私,或者隐藏某些不健康的画面. 原理 要实现马赛克的效果,需

HDU 4819 Mosaic D区段树

pid=4819">点击打开链接 Mosaic Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 657    Accepted Submission(s): 248 Problem Description The God of sheep decides to pixelate some pictures (i.e., ch

HDOJ 4819 Mosaic

裸的二维线段树.... Mosaic Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 494    Accepted Submission(s): 177 Problem Description The God of sheep decides to pixelate some pictures (i.e., change the

HDU 4819 Mosaic

题意: 一个矩形内每个格子都有一个值  现在有q个操作  每个操作给出坐标(x,y)和长度L  每次操作输出以(x,y)为中心的边长为L的矩形内的最大值和最小值之和的一半  并将这个值更新到(x,y)坐标上 思路: 区间查询最大最小值  单点更新  明显是线段树的特征  不过这里是二维的线段树  我用的是树套树的写法 我对二维线段树的理解:(个人理解不一定正确) 初始化麻烦  相当于做n*n次单点更新 树套树操作的思维就先找到满足第一位的区间  这个区间对应几棵树  然后在这几棵树(即第二维)里

树套树+【UVALive】6709 Mosaic 二维线段树

题目链接:6709 Mosaic 题解:参考这个博客:二维线段树,先按行建树然后每一个节点也是一个棵线段树按列建. #include<bits/stdc++.h> #include<cmath> #include<set> #include<cstdio> #include<iomanip> #include<iostream> #include<string> #include<cstring> #inclu

HDU 4819 Mosaic --二维线段树(树套树)

题意: 给一个矩阵,每次查询一个子矩阵内的最大最小值,然后更新子矩阵中心点为(Max+Min)/2. 解法: 由于是矩阵,且要求区间最大最小和更新单点,很容易想到二维的线段树,可是因为之前没写过二维的线段树,所以没跳出来.后来熟悉了一下,原来很多细节地方都没有考虑到. 这里build,update,query都分为两个函数,第一个为Y轴的(sub_update),第二个为X轴的(update),不仅每个sub_update或sub_build后面要加Y轴的pushup函数,而且每个update或