Dasha decided to have a rest after solving the problem D and began to look photos from previous competitions.
Let's call photos as the matrix with the size n × m, which consists of lowercase English letters.
Some k photos especially interested her, because they can be received from photo-template by painting a rectangular area in a certain color. Let's call such photos special.
More formally the i-th special photo is received from the photo-template by replacing all characters on some rectangle with upper left corner of the cell with coordinates (ai, bi) and lower right corner in the cell with coordinates (ci, di) to the symbol ei.
Dasha asks you to find the special photo so that the total distance from it to all other special photos is minimum. And calculate this distance.
Determine the distance between two photos as the sum of distances between all corresponding letters. The distance between two letters is the difference module of their positions in the alphabet. For example, the distance between letters 'h' and 'm' equals |8 - 13| = 5, because the letter 'h' is the 8-th in the alphabet, the letter 'm' is the 13-th.
The first line contains three integers n, m, k (1 ≤ n, m ≤ 103, 1 ≤ k ≤ 3·105) — the number of strings in the photo-template, the number of columns and the number of special photos which are interesting for Dasha.
The next n lines contains the string with m length which consists of little Latin characters — the description of the photo-template.
Each of the next k lines contains the description of the special photo in the following format, "ai bi ci di ei" (1 ≤ ai ≤ ci ≤ n, 1 ≤ bi ≤ di ≤ m), where (ai, bi) — is the coordinate of the upper left corner of the rectangle, (ci, di) — is the description of the lower right corner, and ei — is the little Latin letter which replaces the photo-template in the described rectangle.
In the only line print the minimum total distance from the found special photo to all other special photos.
3 3 2 aaa aaa aaa 1 1 2 2 b 2 2 3 3 c
10
5 5 3 abcde eabcd deabc cdeab bcdea 1 1 3 4 f 1 2 3 3 e 1 3 3 4 i
59
In the first example the photos are following:
bba aaa bba acc aaa acc
The distance between them is 10.
Title:
Give you an alphabetic matrix of n * m n * m, and then give you kk independent operations, each operation is to cover a subrectangle of the original matrix with a given character.
A new matrix after operation is called a special matrix.
Defining the difference between two matrices is the sum of absolute difference values of the corresponding letter ASCII codes
Find a special matrix to minimize the sum of the difference values between it and the remaining k_1k_1 special matrix.
Output Minimum
n*m is not big, so you can try to preprocess the answer for each character.
Firstly, k matrices are inserted and deleted at line a and C. Because the covering part is a rectangle, the column corresponds to an interval.
Method 1:
For each row, column [1,m] is an interval. To insert or delete the row is to add or subtract the interval. When calculating the answer of each point, we first make a single point query in the 26 line segment tree, find out the number of occurrences of each character at this point in this k operation, and take out the answer corresponding to each letter (note that some matrices do not cover the current point, we need to count the letters of the original matrix). Then enumerate the filled letters and calculate them directly.
Next is the statistical answer: to fill in each letter, the original matrix has been found out each answer, do a two-dimensional prefix sum, and then enumerate k matrices, subtract the answer covering the rectangle on the answer of the original matrix, and then fill in the answer of the corresponding letter, and get the answer of the matrix.
Time complexity O(26nmlogm) can pass through all data.
Note that there is a special application of line segment tree here. Because the line segment tree in this question is an interval update and a single point query, it does not need lazy tag, as long as the query path from the root node to the query point, plus the weights of the nodes passing through the path.
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<stack> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define fi first #define se second #define mp make_pair typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; const ll inf=0x3fffffffffffff; const ll mod=1000000007; const int maxn=1e3+100; struct node { int x1,y1,x2,y2,kind; }a[maxn*300]; int seg[30][maxn*4]; //26 segment trees, recording 26 characters char map[maxn][maxn]; VI in[maxn],out[maxn]; int cnt[30]; ll p[maxn][maxn],s[30][maxn][maxn]; //Two Binary Prefixes and Sums void update(int i,int l,int r,int L,int R,int *t,int v) //Interval update { if(L==l&&R==r) { t[i]+=v; return; } int m=(L+R)/2; if(r<=m) update(i*2,l,r,L,m,t,v); else if(l>m) update(i*2+1,l,r,m+1,R,t,v); else { update(i*2,l,m,L,m,t,v); update(i*2+1,m+1,r,m+1,R,t,v); } } int query(int i,int pos,int L,int R,int *t) { if(L==R) return t[i]; int m=(L+R)/2; if(pos<=m) return t[i]+query(i*2,pos,L,m,t); //It is not necessary to use lazy marker for single point query after interval updating. It is only necessary to add the weights of all points along the path from the root to this point of the online segment tree. else return t[i]+query(i*2+1,pos,m+1,R,t); } int main() { int n,m,k; scanf("%d%d%d",&n,&m,&k); rep(i,1,n+1) scanf("%s",map[i]+1); rep(i,0,k) { scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); in[a[i].x1].pb(i),out[a[i].x2].pb(i); char str[10]; scanf("%s",str); a[i].kind=str[0]-'a'; } rep(i,1,n+1) { vector<int>::iterator it; for(it=in[i].begin();it!=in[i].end();it++) { update(1,a[*it].y1,a[*it].y2,1,m,seg[a[*it].kind],1); } rep(j,1,m+1) { int num=0; ll sum=0; memset(cnt,0,sizeof(cnt)); rep(x,0,26) { cnt[x]+=query(1,j,1,m,seg[x]); num+=cnt[x]; sum+=cnt[x]*x; } cnt[map[i][j]-'a']+=k-num; sum+=(map[i][j]-'a')*(k-num); rep(x,0,26) { if(x==map[i][j]-'a') p[i][j]=p[i-1][j]+p[i][j-1]-p[i-1][j-1]+sum; //Sum of the difference values of the other k sub-matrices (1,1)-(i,j) recorded by p[i][j] s[x][i][j]=s[x][i-1][j]+s[x][i][j-1]-s[x][i-1][j-1]+sum; //s[x][i][j] denotes the sum of the differences between the sub-matrices (1,1)-(i,j) and the other k after filling in the characters'a'+x if(x>0) cnt[x]+=cnt[x-1]; sum+=cnt[x]-(k-cnt[x]); //Sum is the sum of the difference between point (i,j) and other k values when filling in the character'a'+x. Sum is updated with the change of x. } } for(it=out[i].begin();it!=out[i].end();it++) { update(1,a[*it].y1,a[*it].y2,1,m,seg[a[*it].kind],-1); } } ll ans=inf; rep(i,0,k) { ll res=p[n][m]-p[a[i].x2][a[i].y2]+p[a[i].x1-1][a[i].y2]+p[a[i].x2][a[i].y1-1]-p[a[i].x1-1][a[i].y1-1]; //First remove the part to be filled in and calculate the difference between the other parts. res+=s[a[i].kind][a[i].x2][a[i].y2]-s[a[i].kind][a[i].x1-1][a[i].y2]-s[a[i].kind][a[i].x2][a[i].y1-1]+s[a[i].kind][a[i].x1-1][a[i].y1-1];//Add the difference of this part and ans=min(ans,res); } printf("%lld\n",ans); return 0; }
There's actually a quicker way to do it.
log can actually be removed.
For each rectangular parameter a,b,c,d, the corresponding characters are marked with + 1 at (a,b), (c+1,d+1), (c+1,b) and (a,d+1). Then we find the prefix sum. It can be found that for the prefix sum of any rectangle, if it is inside the rectangle, it is just + 1, otherwise it is 0. (Draw a picture, you know)
The next step is to enumerate the letters of each location, then two-dimensional prefix sum. Do the same as before
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<stack> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define fi first #define se second #define mp make_pair typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; const ll inf=0x3fffffffffffff; const ll mod=1000000007; const int maxn=1e3+100; struct node { int x1,y1,x2,y2,kind; }a[maxn*300]; char map[maxn][maxn]; int cnt[30]; ll p[maxn][maxn],s[30][maxn][maxn]; //Two Binary Prefixes and Sums int g[30][maxn][maxn]; int main() { int n,m,k; scanf("%d%d%d",&n,&m,&k); rep(i,1,n+1) scanf("%s",map[i]+1); rep(i,0,k) { scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); char str[10]; scanf("%s",str); a[i].kind=str[0]-'a'; g[a[i].kind][a[i].x1][a[i].y1]++,g[a[i].kind][a[i].x2+1][a[i].y2+1]++; g[a[i].kind][a[i].x1][a[i].y2+1]--,g[a[i].kind][a[i].x2+1][a[i].y1]--; } rep(i,1,n+1) { rep(j,1,m+1) { int num=0; ll sum=0; memset(cnt,0,sizeof(cnt)); rep(x,0,26) { g[x][i][j]+=g[x][i-1][j]+g[x][i][j-1]-g[x][i-1][j-1]; //Two-dimensional prefix and update cnt[x]=g[x][i][j]; num+=cnt[x]; sum+=cnt[x]*x; } cnt[map[i][j]-'a']+=k-num; sum+=(map[i][j]-'a')*(k-num); rep(x,0,26) { if(x==map[i][j]-'a') p[i][j]=p[i-1][j]+p[i][j-1]-p[i-1][j-1]+sum; //Sum of the difference values of the other k sub-matrices (1,1)-(i,j) recorded by p[i][j] s[x][i][j]=s[x][i-1][j]+s[x][i][j-1]-s[x][i-1][j-1]+sum; //s[x][i][j] denotes the sum of the differences between the sub-matrices (1,1)-(i,j) and the other k after filling in the characters'a'+x if(x>0) cnt[x]+=cnt[x-1]; sum+=cnt[x]-(k-cnt[x]); //Sum is the sum of the difference between point (i,j) and other k values when filling in the character'a'+x. Sum is updated with the change of x. } } } ll ans=inf; rep(i,0,k) { ll res=p[n][m]-p[a[i].x2][a[i].y2]+p[a[i].x1-1][a[i].y2]+p[a[i].x2][a[i].y1-1]-p[a[i].x1-1][a[i].y1-1]; //First remove the part to be filled in and calculate the difference between the other parts. res+=s[a[i].kind][a[i].x2][a[i].y2]-s[a[i].kind][a[i].x1-1][a[i].y2]-s[a[i].kind][a[i].x2][a[i].y1-1]+s[a[i].kind][a[i].x1-1][a[i].y1-1];//Add the difference of this part and ans=min(ans,res); } printf("%lld\n",ans); return 0; }