hdu step5.3.3 Median Filter(树状数组求第k大的值)

来源:互联网 发布:顶级域名有几种类型 编辑:程序博客网 时间:2024/04/29 04:33

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;

}

 

 

0 0