Auteur du problème : | TheSensei |
Préparé par : | Hasan Saleh (MathModel) |
Édité par : | Hasan Saleh (MathModel) |
Solution
Vous avez une grille n\times m . Définissez le coût de la cellule comme
c'est-à-dire sa valeur multipliée par la distance de Manhattan à la bordure la plus proche. Vous devez répondre à requêtes, chacune donnant un sous-rectangle (l_1,r_1)–(l_2,r_2). Traitez cette sous-grille comme une nouvelle grille n'\times m' (réindexée de à (n',m')) et calculez la somme de ses coûts.
Le poids
dépend uniquement des positions (i',j') dans la sous-grille, et non des indices originaux. Nous avons besoin de \sum A[i][j]\times w_{i',j'} sur le rectangle en par requête.
Utilisez trois structures de somme préfixe :
Somme préfixe 2D standard
Somme préfixe diagonale
le long de la diagonale haut-gauche bas-droit.
Somme préfixe anti-diagonale
le long de la diagonale haut-droit bas-gauche.
Chaque sous-grille a \left\lfloor\min(n',m')/2\right\rfloor "couches." Vous pouvez exprimer la somme totale pondérée comme
où chaque v_k est lu en à partir des trois tables de préfixe.
#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;
// pour trouver la somme (k varie de 0 à 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]
// donc, je sépare les 4 termes, comme 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;
// SOLUTION brute force
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();
}
}Complexité \mathcal{O}(nm+q)