hdoj 48119 Mosaic (二維線段樹 單點更新)

Mosaic

點擊打開鏈接

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


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

這是我看着匡冰大神的博客寫的,第一次寫這玩意兒,自己寫老是錯,求大神指點
我寫的代碼大哭大哭
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define MAX  1010
#define inf 0x7fffffff
struct node
{
	int L;
	int R;
	int vmax;
	int vmin;
};

struct node1
{
	int hl;
	int hr;
	node subt[4*MAX];
}t[4*MAX];

void build_subt(int v,int rt,int l,int r)
{
 t[v].subt[rt].L=l;
 t[v].subt[rt].R=r;
 t[v].subt[rt].vmax=-inf;
 t[v].subt[rt].vmin=inf;
 if(l==r)
   return ;
  int mid=(l+r)>>1;
  build_subt(v,rt<<1,l,mid);
  build_subt(v,rt<<1|1,mid+1,r);
} 

void build(int v,int l,int r,int ll,int rr)
{
	t[v].hl=l;
	t[v].hr=r;
	build_subt(v,1,ll,rr);
	if(l==r)
	return ;
	int mid=(l+r)>>1;
	build(v<<1,l,mid,ll,rr);
	build(v<<1|1,mid+1,r,ll,rr);
}

void update_subt(int v,int rt,int pos,int x)
{
	t[v].subt[rt].vmax=max(x,t[v].subt[rt].vmax); 
	t[v].subt[rt].vmin=min(x,t[v].subt[rt].vmin); 
	if(t[v].subt[rt].L==t[v].subt[rt].R)
	return ;
	int mid=(t[v].subt[rt].L+t[v].subt[rt].R)>>1;
	if(pos<=mid)
	update_subt(v,rt<<1,pos,x);
	else
	update_subt(v,rt<<1|1,pos,x);
	t[v].subt[rt].vmax=max(t[v].subt[rt<<1].vmax,t[v].subt[rt<<1|1].vmax);
	t[v].subt[rt].vmin=min(t[v].subt[rt<<1].vmin,t[v].subt[rt<<1|1].vmin);
}

void update(int v,int cur,int x,int y)
{
	update_subt(v,1,x,y);
	if(t[v].hl==t[v].hr)
	return ;
	int mid=(t[v].hl+t[v].hr)>>1;
	if(cur<=mid)
	update(v<<1,cur,x,y);
	else
	update(v<<1|1,cur,x,y);
}

int query_subtmax(int v,int rt,int l,int r)
{
	if(t[v].subt[rt].L==l&&t[v].subt[rt].R==r)
	return t[v].subt[rt].vmax;
	int mid=(t[v].subt[rt].L+t[v].subt[rt].R)>>1;
	if(r<=mid)
	 return query_subtmax(v,rt<<1,l,r);
	else if(l>mid)
	return query_subtmax(v,rt<<1|1,l,r);
	else
	return max(query_subtmax(v,rt<<1,l,mid),query_subtmax(v,rt<<1|1,mid+1,r));
	 
}

int querymax(int v,int l,int r,int ll,int rr)
{
	if(t[v].hl==l&&t[v].hr==r)
	return query_subtmax(v,1,ll,rr);
	
	int mid=(t[v].hl+t[v].hr)>>1;
	if(r<=mid)
	return querymax(v<<1,l,r,ll,rr);
	else if(l>mid)
	return querymax(v<<1|1,l,r,ll,rr);
	else 
	return max(querymax(v<<1,l,mid,ll,rr),querymax(v<<1|1,mid+1,r,ll,rr));
}


int query_subtmin(int v,int rt,int l,int r)
{
	if(t[v].subt[rt].L==l&&t[v].subt[rt].R==r)
	return t[v].subt[rt].vmin;
	int mid=(t[v].subt[rt].L+t[v].subt[rt].R)>>1;
	if(r<=mid)
	 return query_subtmin(v,rt<<1,l,r);
	else if(l>mid)
	return query_subtmin(v,rt<<1|1,l,r);
	else
	return min(query_subtmin(v,rt<<1,l,mid),query_subtmin(v,rt<<1|1,mid+1,r));
	 
}

int querymin(int v,int l,int r,int ll,int rr)
{
	if(t[v].hl==l&&t[v].hr==r)
	return query_subtmin(v,1,ll,rr);
	
	int mid=(t[v].hl+t[v].hr)>>1;
	if(r<=mid)
	return querymin(v<<1,l,r,ll,rr);
	else if(l>mid)
	return querymin(v<<1|1,l,r,ll,rr);
	else 
	return min(querymin(v<<1,l,mid,ll,rr),querymin(v<<1|1,mid+1,r,ll,rr));
}
int main()
{
	int T,ca=1;
	scanf("%d",&T);
	while(T--)
	{
	  int n;
	  scanf("%d",&n);
	  build(1,1,n,1,n);  
	  for(int i=1;i<=n;i++)
	   for(int j=1;j<=n;j++)
	   {
	   	int v;
	   	scanf("%d",&v);
		update(1,v,i,j);
	   }
	   int Q;
	   scanf("%d",&Q);
	   printf("Case #%d:\n",ca++);
	   while(Q--)
	   {
	   	int xi,yi,Li;
	   	scanf("%d%d%d",&xi,&yi,&Li);
         int x1 = max(xi - Li/2,1);
         int x2 = min(xi + Li/2,n);
         int y1 = max(yi - Li/2,1);
         int y2 = min(yi + Li/2,n);
         if(x1>x2)
         swap(x1,x2);
         if(y1>y2)
         swap(y1,y2);
		 int Max = querymax(1,x1,x2,y1,y2);
         int Min = querymin(1,x1,x2,y1,y2);
         int t = (Max+Min)/2;
         printf("%d\n",t);
         update(1,t,xi,yi);
	   }
	}
	return 0;
}

匡冰大神版本,大神就是大神:點擊打開鏈接
#include<cstdio>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define inf 0x7ffffff
#define MAXN 1010
int n;
struct nodey
{
	int ly;
	int ry;
	int vmax;
	int vmin;
};
int locate_y[MAXN],locate_x[MAXN];
struct nodex
{
	int lx,rx;
	nodey sty[MAXN*4];
	void build(int l,int r,int v)
	{
		sty[v].ly=l;
		sty[v].ry=r;
		sty[v].vmax=-inf;
		sty[v].vmin=inf;
		if(l==r)
		{
		 locate_y[l]=v;
		 return ;	
		}	
	    int mid=(l+r)>>1;
    	build(l,mid,v<<1);
	    build(mid+1,r,v<<1|1);
	}
   
   int querymin(int l,int r,int v)
   {
   	if(sty[v].ly==l&&sty[v].ry==r)
   	return sty[v].vmin;
   	
   	int mid=(sty[v].ly+sty[v].ry)>>1;
   	if(r<=mid)
   	return querymin(l,r,v<<1);
   	else if(l>mid)
   	return querymin(l,r,v<<1|1);
   	else
   	return min(querymin(l,mid,v<<1),querymin(mid+1,r,v<<1|1));
   }
   
   int querymax(int l,int r,int v)
   {
   	if(sty[v].ly==l&&sty[v].ry==r)
   	return sty[v].vmax;
   	
   	int mid=(sty[v].ly+sty[v].ry)>>1;
   	if(r<=mid)
   	return querymax(l,r,v<<1);
   	else if(l>mid)
   	return querymax(l,r,v<<1|1);
   	else
   	return max(querymax(l,mid,v<<1),querymax(mid+1,r,v<<1|1));
   }	
}stx[MAXN*4];

void build(int l,int r,int v)
{
	stx[v].lx=l;
	stx[v].rx=r;
	stx[v].build(1,n,1);
	if(l==r)
	{
		locate_x[l]=v;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,v<<1);
	build(mid+1,r,v<<1|1);
}

void update(int x,int y,int va)
{
	int tx=locate_x[x];
	int ty=locate_y[y];
	stx[tx].sty[ty].vmin=stx[tx].sty[ty].vmax=va;
	for(int i=tx;i;i>>=1)
	  for(int j=ty;j;j>>=1)
	  {
	  	if(i==tx&&j==ty)
	  	continue;
	  	if(j==ty)
	  	{
	  	  stx[i].sty[j].vmin=min(stx[i<<1].sty[j].vmin,stx[i<<1|1].sty[j].vmin);
		  stx[i].sty[j].vmax=max(stx[i<<1].sty[j].vmax,stx[i<<1|1].sty[j].vmax);	
		}
		else
		{
	  	  stx[i].sty[j].vmin=min(stx[i].sty[j<<1].vmin,stx[i].sty[j<<1|1].vmin);
		  stx[i].sty[j].vmax=max(stx[i].sty[j<<1].vmax,stx[i].sty[j<<1|1].vmax);	
		}
	  }
}

int querymin(int x1,int x2,int y1,int y2,int v)
{
	if(stx[v].lx==x1&&stx[v].rx==x2)
	return stx[v].querymin(y1,y2,1);
	int mid=(stx[v].lx+stx[v].rx)>>1;
	if(x2<=mid)
	return querymin(x1,x2,y1,y2,v<<1);
	else if(x1>mid)
	return querymin(x1,x2,y1,y2,v<<1|1);
	else
	return min(querymin(x1,mid,y1,y2,v<<1),querymin(mid+1,x2,y1,y2,v<<1|1));
}

int querymax(int x1,int x2,int y1,int y2,int v)
{
	if(stx[v].lx==x1&&stx[v].rx==x2)
	return stx[v].querymax(y1,y2,1);
	int mid=(stx[v].lx+stx[v].rx)>>1;
	if(x2<=mid)
	return querymax(x1,x2,y1,y2,v<<1);
	else if(x1>mid)
	return querymax(x1,x2,y1,y2,v<<1|1);
	else
	return max(querymax(x1,mid,y1,y2,v<<1),querymax(mid+1,x2,y1,y2,v<<1|1));
}

int main()
{
 int T,ca=1;
 scanf("%d",&T);
 while(T--)
 {
 	scanf("%d",&n);
 	build(1,n,1);
 	for(int i=1;i<=n;i++)
 	 for(int j=1;j<=n;j++)
 	 {
 	   int v;
	   scanf("%d",&v);
	   update(i,j,v);	
	 }
	 int Q;
	 scanf("%d",&Q);
	 printf("Case #%d:\n",ca++);
	 while(Q--)
	 {
	 	int xi,yi,Li;
	 	scanf("%d%d%d",&xi,&yi,&Li);
	 	int x1=max(xi-Li/2,1);
	 	int x2=min(xi+Li/2,n);
	 	int y1=max(yi-Li/2,1);
	 	int y2=min(yi+Li/2,n);
	 	int ret_max=querymax(x1,x2,y1,y2,1);
	 	int ret_min=querymin(x1,x2,y1,y2,1);
	 	int ans=(ret_max+ret_min)>>1;
	 	printf("%d\n",ans);
	 	update(xi,yi,ans);
	 }
 }
 return 0;	
} 






發佈了221 篇原創文章 · 獲贊 17 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章