#P9026. [2017年备战省选]矩阵

[2017年备战省选]矩阵

/*.....................
Author : PTY
Time : 12/11/28
.....................*/
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
#include <complex>
using namespace std;

#define rep(i,l,r) for(int i=l;i<=r;i++)
#define drep(i,r,l) for(int i=r;i>=l;i--)
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define LL long long
#define Travel(E, u) for(int i=E.start[u],v;v=E.e[i].a,i;i=E.e[i].next)
#define sqr(x) ((x)*(x))
#define pb push_back
#define pi 3.1415926535897932384626433832795
#define read() (strtol(ipos, &ipos, 10))
const int maxn = 2124290, maxx = 50000008;
int R, C, H, W, X, Y, K;
const int N = 1100;
int a[N][N], b[N][N], ans[N][N];
int tot;
struct arr
{
	int x, y, sco;
	arr(){}
	arr(int x1, int y1, int sco1){x = x1; y = y1; sco = sco1;}
	bool operator<(const arr &t)const
	{
		return sco < t.sco || sco == t.sco && x < t.x || sco == t.sco && x == t.x && y < t.y;	
	}
}tmp[N*N];
struct Tcomplex
{
	double r, i;
};
Tcomplex A[maxn], B[maxn];
int b1, b2, a1, a2, ta1[N], ta2[N];
char Input[maxx+8], *ipos;
struct Tfft
{
	Tcomplex W[maxn];
	int n, H;
	int rev[maxn];
	void init(int N)
	{
		n = N; W[0].r = 1.0; W[0].i = 0;
		H = 0; while ((1<<H) < n) H++;
		int tmp = 1; Tcomplex w;
		rep(i,1,2*N-1)
		{
			if (i == tmp) 
			{
				w.r = cos(2*pi/tmp); w.i = sin(2*pi/tmp);
				tmp<<=1;
			}	
			if (i & 1) 
			{
				W[i].r = W[i>>1].r * w.r - W[i>>1].i * w.i;
				W[i].i = W[i>>1].i * w.r + W[i>>1].r * w.i;
			}
			else W[i] = W[i>>1];
		}
		rep(i,0,n-1)
		{
			int s = 0, j = i;
			rep (k,1,H) s = (s << 1) + (j & 1), j >>= 1;
			rev[s] = i;	
		}
	}
	void dft(Tcomplex a[])
	{
		rep(i,0,n-1) if (rev[i] < i) swap(a[rev[i]], a[i]);
		Tcomplex *p, *p1, *p2;
		int i;
		for (int h = 0, s = 1; h < H; h++, s <<= 1)
		{
			p = W + s + s;
			for (int st = 0; st < n; st += s + s, p = W + s + s)
				for (p1=a+st, p2=a+st+s, i = st; i < st + s; i++, p++, p1++, p2++)
				{
					Tcomplex &v1 = *p1, &v2 = *p2;
					double tr = v2.r*p->r-v2.i*p->i, ti = v2.i*p->r+v2.r*p->i;
					v2.r = v1.r - tr; v2.i = v1.i - ti;
					v1.r += tr; v1.i += ti;
				}
		}
	}
	void cheng(Tcomplex A[], Tcomplex B[])
	{
		dft(A); dft(B);
		rep(i,0,n-1) 
		{
			double t = A[i].r;
			A[i].r = (A[i].r*B[i].r-A[i].i*B[i].i) / n;
			A[i].i = (t*B[i].i+A[i].i*B[i].r) / n;
		}
		dft(A);
		rep(i,1,n-1>>1) swap(A[i], A[n-i]);
	}
}FFT;
struct Tprogram
{
    void close(){}
    void init()
    {
		fread(ipos=Input, 1, maxx, stdin);
		R = read(); C = read();
		rep(i,0,R-1) rep(j,0,C-1) a[i][j] = read();
		H = read(); W = read();
		rep(i,0,H-1) rep(j,0,W-1) b[i][j] = read();
		X = read(); Y = read(); X--; Y--;
		K = read();
    }
    void get_dian()
    {
		int n1 = R, n2 = C;
		int n = 1;
		while (n < n1 * n2) n <<= 1;
		FFT.init(n);
		rep(i,0,R-1) rep(j,0,C-1) A[i*n2+j].r = a[i][j];
		rep(i,0,H-1) rep(j,0,W-1) B[i*n2+j].r = b[H-i-1][W-j-1];
		FFT.cheng(A, B);
		rep(i,0,n-1)
		{
			int x = i / n2, y = i - n2 * x;
			if (x >= H - 1 && y >= W - 1) 
				ans[x-H+1][y-W+1] = -2*round(A[i].r); 
		}
	}
    void others()
    {
		rep(i,0,H-1) rep(j,0,W-1) b1 = b1 + b[i][j], b2 = b2 + b[i][j] * b[i][j];	
		rep(k,0,H-1)
			rep(j,0,C-1)
		 		ta1[j] += a[k][j], ta2[j] += a[k][j]*a[k][j];
		rep(i,0,R-H)
		{
			int a1 = 0, a2 = 0;
			rep(j,0,W-1) a1 += ta1[j], a2 += ta2[j];
			rep(j,0,C-W)
			{
				ans[i][j] += a2 + b2 + (a[i+X][j+Y])*(a[i+X][j+Y])*H*W - 2*a1*a[i+X][j+Y] + 2*b1*a[i+X][j+Y];
				a1 -= ta1[j], a2 -= ta2[j];
				a1 += ta1[j+W], a2 += ta2[j+W];
			}
			rep(j,0,C-1)
				ta1[j] -= a[i][j], ta1[j] += a[i+H][j],
				ta2[j] -= a[i][j]*a[i][j], ta2[j] += a[i+H][j]*a[i+H][j];
		}
	}
	void make_ans()
	{
		rep(i,0,R-H)
			rep(j,0,C-W) tmp[++tot] = arr(i + 1, j + 1, ans[i][j]);	
		sort(tmp+1, tmp+tot+1);
		rep(i,1,K)
			printf("%d %d %d\n", tmp[i].x, tmp[i].y, tmp[i].sco);
	}
    void work()
    {
		get_dian();	
		others();
		make_ans();
    }
}Program;

int main()
{
    Program.open();
    Program.init();
    Program.work();
    Program.close();
    return 0;
}