Problem Müəllifi: | TheSensei |
Hazırlayan: | Hasan Saleh (MathModel) |
Redaktə edən: | Hasan Saleh (MathModel) |
Həll
Sizdə n\times m ölçülü bir şəbəkə var. Hüceyrənin qiymətini aşağıdakı kimi müəyyən edin:
yəni, onun dəyəri ilə ən yaxın sərhədin Manhattan məsafəsi. Siz sorğusuna cavab verməlisiniz, hər biri (l_1,r_1)–(l_2,r_2) alt-dikdörtgenini verir. O alt-şəbəkəni yeni n'\times m' şəbəkə (-dən (n',m')-ə yenidən indekslənmiş) kimi qəbul edin və onun qiymətlərinin cəmini hesablayın.
Çəki
yalnız alt-şəbəkədəki (i',j') mövqelərindən asılıdır, orijinal indekslərdən deyil. Biz \sum A[i][j]\times w_{i',j'}-ni -də sorğu başına hesablamağa ehtiyac var.
Üç prefiks cəmi strukturu istifadə edin:
Standart 2D prefiks cəmi
Diagonal prefiks
yuxarı-solaşa-sağ boyunca.
Anti-diagonal prefiks
yuxarı-sağaşa-sol boyunca.
Hər bir alt-şəbəkənin \left\lfloor\min(n',m')/2\right\rfloor "qat"ı var. Ümumi çəkilmiş cəmi aşağıdakı kimi ifadə edilə bilər:
burada hər v_k üç prefiks cədvəlindən -də oxunur.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
void solve()
{
ll n,m;
cin>>n>>m;
vector<vector<ll>> num(n+1,vector<ll>(m+1));
for(ll i=1; i<=n; i++) for(ll j=1; j<=m; j++) cin>>num[i][j];
vector<vector<ll>> p(n+1,vector<ll>(m+1,0));
for(ll i=1; i<=n; i++) for(ll j=1; j<=m; j++) p[i][j]=p[i-1][j]+p[i][j-1]-p[i-1][j-1]+num[i][j];
vector<vector<ll>> pd1(n+1,vector<ll>(m+1,0));
for(ll i=1; i<=n; i++) for(ll j=1; j<=m; j++) pd1[i][j]=pd1[i-1][j-1]+p[i][j];
vector<vector<ll>> pd2(n+2,vector<ll>(m+2,0));
for(ll i=1; i<=n; i++) for(ll j=0; j<=m; j++) pd2[i][j]=pd2[i-1][j+1]+p[i][j];
ll q;
cin>>q;
while(q--)
{
ll l1,r1,l2,r2;
cin>>l1>>r1>>l2>>r2;
// to find summation (k varies from 0 to floor(min(l2-l1,r2-r1)/2)) p[l2-k][r2-k]-p[l1-1+k][r2-k]-p[l2-k][r1-1+k]+p[l1-1+k][r1-1+k]
// so, i am seperating the 4 terms, as v1-v2-v3+v4
ll k = min(l2-l1,r2-r1)/2;
ll v1 = pd1[l2][r2]-pd1[max((ll)0,l2-k-1)][max((ll)0,r2-k-1)];
ll v2 = pd2[max((ll)0,l1-1+k)][max((ll)0,r2-k)]-pd2[max((ll)0,l1-2)][max((ll)0,r2+1)];
ll v3 = pd2[l2][r1-1]-pd2[max((ll)0,l2-k-1)][max((ll)0,r1+k)];
ll v4 = pd1[max((ll)0,l1+k-1)][max((ll)0,r1+k-1)]-pd1[max((ll)0,l1-2)][max((ll)0,r1-2)];
ll ans1=v1-v2-v3+v4;
//bruteforce SOLUTION
v1=0;
v2=0;
v3=0;
v4=0;
while(l1<=l2 && r1<=r2)
{
v1+=p[l2][r2];
v2+=p[l1-1][r2];
v3+=p[l2][r1-1];
v4+=p[l1-1][r1-1];
l1++;
r1++;
l2--;
r2--;
}
ll ans2=v1-v2-v3+v4;
cout<<ans1<<"\n";
}
}
int main()
{
IOS;
int t;cin>>t;
while(t--){
solve();
}
}Komplekslik \mathcal{O}(nm+q)