记录编号 95836 评测结果 AAAAAAAAAA
题目名称 [HAOI 2007]修筑绿化带 最终得分 100
用户昵称 GravatarMongo 是否通过 通过
代码语言 C++ 运行时间 0.838 s
提交时间 2014-04-09 15:43:31 内存使用 27.05 MiB
显示代码纯文本
//#define lgg
#include <cstdio>
#include <algorithm>
#include <climits>
using namespace std;
int N, M, A, B, C, D, t[1001][1001];
int AB[2][1001][1001], CD[4][1001][1001], ans;
void read(), inti(), calc_AB(), calc_CD(), work(), find_x(), find_y(), minus();
int main()
{
	freopen("parterre.in", "r", stdin); freopen("parterre.out", "w", stdout);
	read();
	inti();
	work();
	printf("%d\n", ans);
	return 0;
}
inline void read()
{
	scanf("%d%d%d%d%d%d", &M, &N, &A, &B, &C, &D);
	for(int i(1); i<=M; ++i)
		for(int j(1); j<=N; ++j)
			scanf("%d", &t[i][j]);
	return;
}
inline void inti()
{
	calc_AB();
	calc_CD();
}
inline void calc_AB()
{
	int sum;
	for(int i(1); i<=M; ++i)
	{
		sum=0;
		for(int j(1); j<=B; ++j)
			sum+=t[i][j];
		AB[1][i][1]=sum;
	}
	for(int i(1); i<=M; ++i)
		for(int j(2); j<=N-B+1; ++j)
			AB[1][i][j]=AB[1][i][j-1]+t[i][j+B-1]-t[i][j-1];
	for(int i(1); i<=N-B+1; ++i)
	{
		sum=0;
		for(int j(1); j<=A; ++j)
			sum+=AB[1][j][i];
		AB[0][1][i]=sum;
	}
	for(int i(1); i<=N-B+1; ++i)
		for(int j(2); j<=M-A+1; ++j)
			AB[0][j][i]=AB[0][j-1][i]+AB[1][j+A-1][i]-AB[1][j-1][i];
	#ifdef lgg
	for(int i(1); i<=M-A+1; ++i)
	{
		for(int j(1); j<=N-B+1; ++j)
		{
			sum=0;
			for(int m(0); m<A; ++m)
				for(int n(0); n<B; ++n)
					sum+=t[i+m][j+n];
			if(sum!=AB[0][i][j])
			{
				printf("error: %d, %d\n", i, j);
				abort();
			}
			printf("%d ", AB[0][i][j]);
		}
		putchar('\n');
	}
	putchar('\n');
	#endif
}
inline void calc_CD()
{
	int sum;
	for(int i(1); i<=M; ++i)
	{
		sum=0;
		for(int j(1); j<=D; ++j)
			sum+=t[i][j];
		CD[1][i][1]=sum;
	}
	for(int i(1); i<=M; ++i)
		for(int j(2); j<=N-D+1; ++j)
			CD[1][i][j]=CD[1][i][j-1]+t[i][j+D-1]-t[i][j-1];
	for(int i(1); i<=N-D+1; ++i)
	{
		sum=0;
		for(int j(1); j<=C; ++j)
			sum+=CD[1][j][i];
		CD[0][1][i]=sum;
	}
	for(int i(1); i<=N-D+1; ++i)
		for(int j(2); j<=M-C+1; ++j)
			CD[0][j][i]=CD[0][j-1][i]+CD[1][j+C-1][i]-CD[1][j-1][i];
	#ifdef lgg
	for(int i(1); i<=M-C+1; ++i)
	{
		for(int j(1); j<=N-D+1; ++j)
		{
			sum=0;
			for(int m(0); m<C; ++m)
				for(int n(0); n<D; ++n)
					sum+=t[i+m][j+n];
			if(sum!=CD[0][i][j])
			{
				printf("error: %d, %d\n", i, j);
				abort();
			}
			printf("%d ", CD[0][i][j]);
		}
		putchar('\n');
	}
	putchar('\n');
	#endif
}
inline void work()
{
	find_x();
	find_y();
	minus();
	return;
}
struct nd
{
	int id, val;
	nd():id(0), val(0){}
	nd(int a, int b):id(a), val(b){}
};
bool operator<=(const nd& a, const nd& b)
{
	return a.val<=b.val;
}
struct dandiao
{
	nd q[1001];
	int beg, end, maxsz;	//end超出范围,maxsz制定单调队列大小
	inline void clear()
	{
		beg=end=0;
		return;
	}
	inline void prepush(nd a)
	{
		int in(end-1);
		while(in>=beg && a<=q[in])
			--in;
		q[++in]=a;
		end=in+1;
		return;
	}
	inline void push(nd a)
	{
		int in(end-1);
		while(in>=beg && a<=q[in])
			--in;
		q[++in]=a;
		end=in+1;
		while(a.id-q[beg].id>=maxsz)
			++beg;
		return;
	}
	inline int front()
	{
		return q[beg].val;
	}
}q;
inline void find_x()
{
	q.maxsz=B-D-1;
	for(int i(1); i<=M-C+1; ++i)
	{
		q.clear();
		for(int j(1); j<q.maxsz; ++j)
			q.prepush(nd(j, CD[0][i][j]));
		for(int j(q.maxsz); j<=N-D+1; ++j)
		{
			q.push(nd(j, CD[0][i][j]));
			CD[2][i][j-q.maxsz+1]=q.front();
		}
	}
	return;
}
inline void find_y()
{
	q.maxsz=A-C-1;
	for(int i(1); i<=N-B+3; ++i)
	{
		q.clear();
		for(int j(1); j<q.maxsz; ++j)
			q.prepush(nd(j, CD[2][j][i]));
		for(int j(q.maxsz); j<=M-C+1; ++j)
		{
			q.push(nd(j, CD[2][j][i]));
			CD[3][j-q.maxsz+1][i]=q.front();
		}
	}
	/*for(int i(1); i<=N-B+3; ++i)
		for(int j(1); j<=M-C+1; ++j)
		{
			int mm(INT_MAX);
			for(int m(0); m<q.maxsz; ++m)
				mm=min(mm, CD[2][j+m][i]);
			if(mm!=CD[3][j][i])
			{
				printf("");
			}
		}*/
	return;
}
inline void minus()
{
	#ifdef lgg
	for(int i(1); i<=M-A+3; ++i)
	{
		for(int j(1); j<=N-B+3; ++j)
		{
			int s(INT_MAX);
			for(int m(0); m<A-C-1; ++m)
				for(int n(0); n<B-D-1; ++n)
					s=min(s, CD[0][i+m][j+n]);
			AB[2][i][j]=s;
			/*if(s!=CD[2][i][j])
			{
				printf("error: %d, %d\n", i, j);
				abort();
			}*/
			printf("%d,%d ", CD[3][i][j], AB[2][i][j]);
		}
		putchar('\n');
	}
	putchar('\n');
	#endif
	for(int i(1); i<=M-A+1; ++i)
		for(int j(1); j<=N-B+1; ++j)
			ans=max(ans, AB[0][i][j]-CD[3][i+1][j+1]);
	return;
}