 /**//*
题意: 给出一个n*n的矩阵,现在对于每一个规模为(2r+1)*(2r+1)的子矩阵,替换其中间元素为该子矩阵的中位数
n<=500 元素<=10^6
可以用树状数组的找第K大来做
用treap会超时
不知别人的500ms怎么做的。。。
*/
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int MAXN = 505;
const int MAXV = 1000050;


int old[MAXN][MAXN],ans[MAXN][MAXN];
int C[MAXV],Max;

 inline int lowbit(int x) {return x&(-x);}

void insert(int p,int val)
  {
while(p<=Max)
 {
C[p]+=val;
p+=lowbit(p);
}
}

int findK(int K)//find the first one >=K
  {
int pos = 0,cnt = 0;
for(int i=20;i>=0;i--)
 {
pos+=(1<<i);
if(pos>=Max||cnt+C[pos]>=K)pos-=(1<<i);
else cnt+=C[pos];
}
return pos+1;
}

int main()
  {
// freopen("in","r",stdin);
int n,r;
while(scanf("%d%d",&n,&r),n)
 {
Max = 0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
 {
scanf("%d",&old[i][j]);
old[i][j]++;
if(old[i][j]>Max)Max = old[i][j];
}

fill(C,C+Max+1,0);

for(int i=1;i<=2*r;i++)
for(int j=1;j<=2*r+1;j++)//
insert(old[i][j],1);

int mid = ((2*r+1)*(2*r+1)+1)/2;
for(int i=2*r+1;i<=n;i++)
 {
if(i&1)//-->
 {
if(i-2*r-1>0)
 {
for(int j=1;j<=2*r+1;j++)
insert(old[i-2*r-1][j],-1);
}
for(int j=1;j<=2*r+1;j++)insert(old[i][j],1);
for(int j=2*r+1;j<=n;j++)
 {
ans[i-r][j-r] = findK(mid);
if(j+1<=n)
 {
for(int t=0;t<2*r+1;t++)
 {
insert(old[i-t][j-2*r],-1);//del
insert(old[i-t][j+1],1);//ins
}
}
}
}
else//<--
 {
for(int j=n;j>=n-2*r;j--)
insert(old[i-2*r-1][j],-1);
for(int j=n;j>=n-2*r;j--)insert(old[i][j],1);
for(int j=n-2*r;j;j--)
 {
ans[i-r][j+r] = findK(mid);
if(j>1)
 {
for(int t=0;t<2*r+1;t++)
 {
insert(old[i-t][j+2*r],-1);//del
insert(old[i-t][j-1],1);//ins
}
}
}
}
}
for(int i=r+1;i<=n-r;i++)
 {
for(int j=r+1;j<=n-r;j++)
printf("%d ",ans[i][j]-1);
puts("");
}
}
return 0;
}
正解应该是这种方法: http://hi.baidu.com/lazy_smartegg/blog/item/db735b8320146824c65cc3bc.html
|
|
常用链接
随笔分类
Links
搜索
最新评论

|
|