题意
给定一个
n⋅m
的字符矩阵,字符集为小写字母。
现在用这个图生成
K
张图,生成方法为:将原图的某一个子矩阵变成相同的某个字符。这样子生成了
两张图的距离定义为对应位置字符ASCll码差的绝对值的和。
n,m≤103,K≤3⋅105
题解
设原图中每个位置的字符为
a(i,j)
。
设
cnt1(i,j,c)
为
(i,j)
在给定的子矩阵中且变成的字符为
c
的图的个数。
设
设
sum1(i,j)
为
f
矩阵从
设
cnt2(i,j,c)
为
(i,j)
是
c
的图的个数(不要求
设
sum2(i,j,c)
为
cnt2
矩阵从
(1,1,c)
至
(i,j,c)
的和:
sum2(i,j,c)=∑ix=1∑jy=1cnt2(x,y,c)
这样之后,枚举每一张图,按如下方法求其他图到它的距离。
- 对于被改变的子矩阵,枚举其他图在这个子矩阵中的字符,并用 sum2 来求其他图在这个子矩阵中的此字符的位置的个数,同时计算距离加到这张图的答案中。
- 对于不在被改变的子矩阵中的位置,其他图与这张图的距离相当于所有图与原图的距离,用 sum1 可以求得。
代码
/// by ztx
/// blog.csdn.net/hzoi_ztx
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v) for(i=v.begin();i!=v.end();i++)
#define r(x) read(x)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}
template <typename TP>inline void readc(TP& ret) {
while (ret=getchar() , ret<'!') ;
while (CH=getchar() , CH>'!') ;
}
template <typename TP>inline void reads(TP *ret) {
ret[0]=0;while (CH=getchar() , CH<'!') ;
while (ret[++ret[0]]=CH,CH=getchar(),CH>'!') ;
ret[ret[0]+1]=0;
}
#define kN 1002LL
#define kC 26LL
#define kK 300010LL
#define infi 0x7f7f7f7f7f7f7f7fLL
struct DATA { int u1, v1, u2, v2, c; } q[kK];
int n, m, K;
int a[kN][kN], str[kN], cnt1[kC][kN][kN];// cnt_changed
ll sum1[kN][kN], sum2[kC][kN][kN];
inline void MI(ll&a, const ll&b) { if (a > b) a = b; }
int main() {
#define u1 q[i].u1
#define u2 q[i].u2
#define v1 q[i].v1
#define v2 q[i].v2
#define c0 q[i].c
int i, j, c, tot;
ll fij, ans, ANS;
r(n), r(m), r(K);
Rep (i,1,n) {
reads(str);
Rep (j,1,m) a[i][j] = str[j] - 'a';
}
Rep (i,1,K) {
r(u1), r(v1), r(u2), r(v2), readc(c0), c0 -= 'a';
++ cnt1[c0][u1][v1];
-- cnt1[c0][u1][v2+1];
-- cnt1[c0][u2+1][v1];
++ cnt1[c0][u2+1][v2+1];
}
Rep (i,1,n) Rep (j,1,m) {
fij = 0;
tot = K;
rep (c,0,26) {
cnt1[c][i][j] += cnt1[c][i-1][j];
cnt1[c][i][j] += cnt1[c][i][j-1];
cnt1[c][i][j] -= cnt1[c][i-1][j-1];
fij += cnt1[c][i][j] * std::abs(a[i][j]-c);
tot -= cnt1[c][i][j];
}
sum1[i][j] = fij + sum1[i-1][j] + sum1[i][j-1] - sum1[i-1][j-1];
rep (c,0,26) {
sum2[c][i][j] = cnt1[c][i][j] + sum2[c][i-1][j] + sum2[c][i][j-1] - sum2[c][i-1][j-1];
if (a[i][j] == c) sum2[c][i][j] += tot;
}
}
ANS = infi;
Rep (i,1,K) {
ans = sum1[n][m] - (sum1[u2][v2]-sum1[u1-1][v2]-sum1[u2][v1-1]+sum1[u1-1][v1-1]);
rep (c,0,26) {
ans += (sum2[c][u2][v2]-sum2[c][u1-1][v2]-sum2[c][u2][v1-1]+sum2[c][u1-1][v1-1])*std::abs(c-c0);
}
MI(ANS,ans);
}
printf("%lld\n", ANS);
END: getchar(), getchar();
return 0;
}