分类:其他 难度:2
题意:给定一张图的每行长度w,及每个点的像素值,以(像素值,持续长度)对表示,求每个像素和周围8个点的差值绝对值的最大值,结果依然以(像素值,持续长度)表示,点数[2,1e9],给定(像素值,持续长度)对的上限为1000对
通过点数的范围可知,这道题不能用O(n)算法遍历,超时;也不能把每个像素点单个存储,超内存。开始考虑对于一个持续长度为len的像素,可知若len超过2w+3,其[w+1,len-w]区间内的点值为0,可省略计算,仍超时。再考虑对某一点,若其上一行从其左上角点开始均为一个像素,其下一行左下角点均为一个像素,且该点不是一个新像素的起始点,则其往后的n个点均为同一个值,n=min(w,上一行像素长度,下一行像素长度,该像素长度),当然还要考虑如果上/下一行为相同元素的情况,以及边界情况。此方法0ms
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define MAX(x,y) (x)>(y)?(x):(y)
#define MIN(x,y) (x)<(y)?(x):(y)
using namespace std;
const int N=1010;
int img[N][2],sum[N];
int w,n,value,length;
void addq(int v,int l)
{
if(v!=value)
{
if(length>0) printf("%d %d\n",value,length);
value=v;
length=l;
}
else
length+=l;
}
int checksub(int x,int y,int offset)
{
int ex=x,ey=y+offset;
while(ey<0&&ex>=0)
{
ex--;
ey+=img[ex][1];
}
if(ex<0) return 0;
while(ey>=img[ex][1] && ex<n)
{
ey-=img[ex][1];
ex++;
}
if(ex>=n) return 0;
return abs(img[x][0]-img[ex][0]);
}
int check(int x,int y)
{
int ans=0;
int num=sum[x]+y;
if(num>=w)
{
if(num%w != 0) ans=MAX(ans,checksub(x,y,-w-1));
ans=MAX(ans,checksub(x,y,-w));
if(num%w != w-1) ans=MAX(ans,checksub(x,y,-w+1));
}
if(num%w != 0) ans=MAX(ans,checksub(x,y,-1));
if(num%w != w-1) ans=MAX(ans,checksub(x,y,1));
if(num<sum[n]-w)
{
if(num%w != 0) ans=MAX(ans,checksub(x,y,w-1));
ans=MAX(ans,checksub(x,y,w));
if(num%w != w-1) ans=MAX(ans,checksub(x,y,w+1));
}
return ans;
}
int getsamelen(int x,int y)
{
if(y==0||y>=img[x][1]-2) return 1;
int num=sum[x]+y;
if(num%w==0 || num%w==w-1) return 1;
int ux=x,uy=y-w-1,dx=x,dy=y+w-1;
int len=img[x][1]-y-1;
if(num>=w)
{
while(uy<0&&ux>=0)
{
ux--;
uy+=img[ux][1];
}
if(img[ux][1]-uy<3) return 1;
if(ux==x) len=MIN(len,w-num%w);
else len = MIN(len,img[ux][1]-uy-1);
}
if(num<sum[n]-w)
{
while(dy>=img[dx][1] && dx<n)
{
dy-=img[dx][1];
dx++;
}
if(img[dx][1]-dy<3) return 1;
if(dx==x) len=MIN(len,MIN(w-num%w,img[x][1]-dy-2));
else len = MIN(len,img[dx][1]-dy-1);
}
return len;
}
int main()
{
while(scanf("%d",&w)&&w)
{
value=length=-1;
int i,j,a,b;
sum[0]=0;
for(i=0;scanf("%d%d",&a,&b)&&(a+b);i++)
{
img[i][0]=a;
img[i][1]=b;
sum[i+1]=img[i][1]+sum[i];
}
img[i][0]=img[i][1]=0;
n=i;
printf("%d\n",w);
for(i=0;i<n;i++)
{
int len=img[i][1];
int ans,samelen;
for(j=0;j<len&&j<=w;)
{
samelen = getsamelen(i,j);
ans=check(i,j);
addq(ans,samelen);
j+=samelen;
}
if(len>=2*w+3)
{
addq(0,len-2*w-2);
j=len-w-1;
}
for(;j<len;)
{
samelen = getsamelen(i,j);
ans=check(i,j);
addq(ans,samelen);
j+=samelen;
}
}
printf("%d %d\n",value,length);
printf("0 0\n");
}
printf("0\n");
}