HDU 4819 Mosaic(二維線段樹)

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

Mosaic

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 401    Accepted Submission(s): 140

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
 

Source
 


題意:
給出一個圖片,分成N×N個單元格,有M次操作,每次操作將(x,y)的值變爲以(x,y) 爲中心L(L爲奇數)爲邊長的區域內的最小值和最大值的均值(floor((maximum+minimum)/2)),並輸出該值。
分析:
明顯的二維線段樹的單點更新和區間查詢,維護最值。
更新肯定是先在二維內找到葉子節點的那棵線段樹,然後再在這棵樹上更新,這部分很簡單,就想成一維的寫。但是這畢竟是二維線段樹,二維的部分也需要維護,當然這部分比較麻煩,我們先想一想一維的:一維的節點維護的是值,我們只要根據它的左右兒子的信息維護(pushup)就行。二維的節點維護的是樹(一維的線段樹),類比一下,我們也需要根據它的左右兒子來維護,但是我們並不能簡單地通過pushup來維護它的信息(因爲一個節點對應的是一棵一維線段樹,而不是一個線段),我們要進入這棵一維線段樹中去維護各個點(線段)的信息。
維護好過後查詢就方便了,簡單地降維即可。

具體請見代碼(so ugly...如何優雅地拍出二維線段樹呢?):
/*
 *
 *	Author	:	fcbruce
 *
 *	Date	:	2014-08-15 08:09:04 
 *
 */
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm 
#define maxn 808

using namespace std;

int n;

int minv[maxn<<2][maxn<<2],maxv[maxn<<2][maxn<<2];

inline int ReadInt()
{
    int flag=0;
    char ch = getchar();
    int data = 0;
    while (ch < '0' || ch > '9')
    {
        if(ch=='-') flag=1;
        ch = getchar();
    }
    do
    {
        data = data*10 + ch-'0';
        ch = getchar();
    }while (ch >= '0' && ch <= '9');
        if(flag) data=-data;
        return data;
}

inline void pushup(int k_2d,int k)
{
	minv[k_2d][k]=min(minv[k_2d][k*2+1],minv[k_2d][k*2+2]);
	maxv[k_2d][k]=max(maxv[k_2d][k*2+1],maxv[k_2d][k*2+2]);
}

//type=1 更新葉子節點的線段樹;	type=0 通過左右兒子維護父線段樹;	下同
void build_1d(int k,int l,int r,int k_2d,int type)
{
	if (r-l==1)
	{
		if (type)
			minv[k_2d][k]=maxv[k_2d][k]=ReadInt();
		else
		{
			minv[k_2d][k]=min(minv[k_2d*2+1][k],minv[k_2d*2+2][k]);
			maxv[k_2d][k]=max(maxv[k_2d*2+1][k],maxv[k_2d*2+2][k]);
		}
	}
	else
	{
		build_1d(k*2+1,l,l+r>>1,k_2d,type);
		build_1d(k*2+2,l+r>>1,r,k_2d,type);
		pushup(k_2d,k);
	}

	
}

void build_2d(int k,int l,int r)
{
	if (r-l==1)
	{
		build_1d(0,0,n,k,1);
		return ;
	}
	
	build_2d(k*2+1,l,l+r>>1);
	build_2d(k*2+2,l+r>>1,r);
	
	build_1d(0,0,n,k,0);
}

void update_1d(int p,int v,int k,int l,int r,int k_2d,int type)
{
	if (r-l==1)
	{
		if (type)
			minv[k_2d][k]=maxv[k_2d][k]=v;
		else
		{
			minv[k_2d][k]=min(minv[k_2d*2+1][k],minv[k_2d*2+2][k]);
			maxv[k_2d][k]=max(maxv[k_2d*2+1][k],maxv[k_2d*2+2][k]);
		}
	}
	else
	{
		int m=l+r>>1;
		if (p<m)
			update_1d(p,v,k*2+1,l,m,k_2d,type);
		else
			update_1d(p,v,k*2+2,m,r,k_2d,type);
		pushup(k_2d,k);
	}
}

void update_2d(int p,int y,int v,int k,int l,int r)
{
	if (r-l==1)
	{
		update_1d(y,v,0,0,n,k,1);
		return ;
	}
	
	int m=l+r>>1;
	if (p<m)
		update_2d(p,y,v,k*2+1,l,m);
	else
		update_2d(p,y,v,k*2+2,m,r);
	
	update_1d(y,v,0,0,n,k,0);
}

pair<int,int> query_1d(int a,int b,int k,int l,int r,int k_2d)
{
	if (b<=l || r<=a)	return make_pair(INF,0);
	if (a<=l && r<=b)
	{
		return make_pair(minv[k_2d][k],maxv[k_2d][k]);
	}
	else
	{
		pair<int,int> v1=query_1d(a,b,k*2+1,l,l+r>>1,k_2d);
		pair<int,int> v2=query_1d(a,b,k*2+2,l+r>>1,r,k_2d);
		
		return make_pair(min(v1.first,v2.first),max(v1.second,v2.second));
	}
}

pair<int,int> query_2d(int a,int b,int ya,int yb,int k,int l,int r)
{
	if (b<=l || r<=a)	return make_pair(INF,0);
	if (a<=l && r<=b)
	{
		return query_1d(ya,yb,0,0,n,k);
	}
	else
	{
		pair<int,int> v1=query_2d(a,b,ya,yb,k*2+1,l,l+r>>1);
		pair<int,int> v2=query_2d(a,b,ya,yb,k*2+2,l+r>>1,r);
		
		return make_pair(min(v1.first,v2.first),max(v1.second,v2.second));
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
		freopen("/home/fcbruce/文檔/code/t","r",stdin);
	#endif // ONLINE_JUDGE
	
	int T_T;
	scanf( "%d",&T_T);
	
	for (int T=1;T<=T_T;T++)
	{
		printf( "Case #%d:\n",T);
		
		scanf( "%d",&n);
		build_2d(0,0,n);
		
		int m,x,y,x1,x2,y1,y2,l;
		scanf( "%d",&m);
		while (m--)
		{
			scanf( "%d %d %d",&x,&y,&l);
			x--;y--;	
			x1=max(x-l/2,0);y1=max(y-l/2,0);
			x2=min(x+l/2+1,n);y2=min(y+l/2+1,n);
			pair<int,int> res=query_2d(x1,x2,y1,y2,0,0,n);
			update_2d(x,y,res.first+res.second>>1,0,0,n);
			printf( "%d\n",res.first+res.second>>1);
		}
	}
	
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章