hdu step5.3.3 Median Filter(樹狀數組求第k大的值)

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;

}

 

 

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