題意
給定一個n?m的字符矩陣,字符集為小寫字母。 現在用這個圖生成K張圖,生成方法為:將原圖的某一個子矩陣變成相同的某個字符。這樣子生成了K張圖,要求選擇某張圖,使得這張圖到其它K?1張圖的距離和最小,只輸出最小距離和。 兩張圖的距離定義為對應位置字符ASCll碼差的絕對值的和。 n,m≤103,K≤3?105
題解
設原圖中每個位置的字符為a(i,j)。 設cnt1(i,j,c)為(i,j)在給定的子矩陣中且變成的字符為c的圖的個數。 設f(i,j)為所有圖(i,j)位置與原圖(i,j)位置距離之和:f(i,j)=∑′z′c=′a′cnt1(i,j,c)?|c?a(i,j)|。 設sum1(i,j)為f矩陣從(1,1)至(i,j)的和:sum1(i,j)=∑ix=1∑jy=1f(x,y)。 設cnt2(i,j,c)為(i,j)是c的圖的個數(不要求(i,j)在給定子矩陣中)。 設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 0x7f7f7f7f7f7f7f7fLLstruct DATA { int u1, v1, u2, v2, c; } q[kK];int n, m, K;int a[kN][kN], str[kN], cnt1[kC][kN][kN];// cnt_changedll 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); }