Hdu 3648 step5.3.3 Median Filter
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1090 Accepted Submission(s): 267
Problem Description
Median filter is a cornerstone of modernimage processing and is used extensively in
Given a black and white image of n by npixels, the algorithm works as follow:
For each pixel p at the i‐th row and the j‐th column (1+ r <= i, j <= n – r), its gray level g[i,j] isreplace by the median of gray levels of pixels in the (2r+1) by (2r+1) squarecentered at p. The square is called the filtering window and r is its radius.
Considering the above example, the graylevel of the pixel at center will be changed from 150 to 124, which is themedian of a filtering window of radius 1.
Note that the algorithm won’t be applied onthe pixels near the boundary, for the filtering window lies outside the image.So you are actually asked to output the filtered sub-image which contains thepixels from (r+1, r+1) to (n-r, n-r).
Input
The input contains several test cases.
For each test case:
(a) The first line contains two integers, nand r, meaning that the size of image is n * n (3 <= n <= 500) and theradius of filtering window is r ( 3 <= 2r + 1 <= n).
(b) The following n lines contains the n byn gray level matrix presenting the image
(c) The gray level ranges from 0 to 1000000The input ends by double 0s.
Output
For each test case output a (n – 2r) by (n– 2r) matrix presenting the sub-image after filtered.
Sample Input
3 1
1 1 1
1 1 1
1 1 1
3 1
1 9 6
4 5 2
3 7 8
3 1
0 0 0
255 255 255
0 255 0
5 1
0 0 1 1 0
1 0 1 0 1
0 0 1 1 1
1 1 1 0 1
1 0 0 0 1
0 0
Sample Output
1
5
0
0 1 1
1 1 1
1 0 1
Hint
The definition of “median”: One type ofaverage, found by arranging the values in order and then selecting the one inthe middle.
If the total number of values in the sampleis even, then the median is the mean of the two middle numbers.
The median is a useful number in caseswhere the distribution has very large extreme values which would otherwise skewthe data.
Source
2010 Asia Regional Hangzhou Site —— OnlineContest
題解:
這道題是一道求中位數的題,因爲數據量大,所以用的是樹狀數組求第k大值的方式,還有S型求值的方法,樹狀數組中存儲的值是某一值出現的次數,p[ans] =j,ans是某一個值,j爲該值出現的次數。S型求中位數,是從第一個正方形開始,求出其中位數,然後奇數行就向右移動,求每個正方形的中位數,當在最右時,則求下一行的最後一個正方形的中位數。偶數行就從最後一個正方形,則向左移動求出中位數,在第一個正方形時,求下一行的第一個正方形的中位數。這樣每次記錄就只需要消去某一行或某一列的所有數值在數組中出現的次數1次和加上新的一行或一列的所有數值出現1次。
這道題目參考是:http://blog.sina.com.cn/s/blog_8161022301010rjj.html。
源代碼:
#include <iostream>
#include <memory.h>
using namespace std;
int p[505][505],st[1100000];
int ans[505][505];
int MAX,r,k,n;
int lowbit(int x)
{
returnx&(-x);
}
void plus(int pos,int x)
{
while(pos<= MAX)
{
st[pos] += x;
pos += lowbit(pos);
}
}
int find_kth()
{
intsum = 0,pos = 0;
for(int i = 20;i >= 0;i--)
{
pos += (1<<i);
if(pos> MAX||sum + st[pos] >= k)
{
pos -= (1<<i);
}
else
sum += st[pos];
}
returnpos+1;
}
void up(int ax,int ay)
{
intq,i,f;
for(f= ay-r;f <= ay+r;f++)
{
plus(p[ax-r-1][f],-1);
plus(p[ax+r][f],1);
}
q = find_kth();
ans[ax][ay] = q;
}
void left(int ax,int ay)
{
intq,i,f;
for(f= ax-r;f <= ax+r;f++)
{
plus(p[f][ay-r-1],-1);
plus(p[f][ay+r],1);
}
q = find_kth();
ans[ax][ay] = q;
}
void right(int ax,int ay)
{
intq,i,f;
for(f= ax-r;f <= ax+r;f++)
{
plus(p[f][ay+r+1],-1);
plus(p[f][ay-r],1);
}
q = find_kth();
ans[ax][ay] = q;
}
void fun()
{
intax,ay;
for(int i = 1;i <= 2*r+1;i++)
{
for(int f = 1;f <= 2*r+1;f++)
plus(p[i][f],1);
}
intp = find_kth();
ans[r+1][r+1] = p;
for(int ax = r+1;ax <= n-r;ax++)
{
if((ax-r)%2)
{
for(ay= r+1;ay <= n-r;ay++)
{
if(ax== ay&&ax == r+1)
{
continue;
}
if(ay== r+1)
up(ax,ay);
else
left(ax,ay);
}
}
else
{
for(ay= n-r;ay >= r+1;ay--)
{
if(ay== n-r)
up(ax,ay);
else
right(ax,ay);
}
}
}
}
void init()
{
memset(st,0,sizeof(st));
}
int main()
{
while(scanf("%d%d",&n,&r) !=EOF&&n+r)
{
init();
k = ((2*r+1)*(2*r+1)+1)/2;
MAX = -1;
for(int i = 1;i <= n;i++)
{
for(int f = 1;f <= n;f++)
{
scanf("%d",&p[i][f]);
p[i][f]++;
if(p[i][f]> MAX)
MAX = p[i][f];
}
}
fun();
for(int i = r+1;i <= n-r;i++)
{
for(int f = r+1;f <= n-r;f++)
printf("%d ",ans[i][f]-1);
printf("\n");
}
}
return0;
}