Codeforces Round #662 (Div. 2) D. Rarity and New Dress 预处理的DP
题意:问给定的矩阵中形如绿色的块的个数。
红色是不合法的。第一个红没有全是同样的字母。第二个红越界。第三个红不是斜的45度
对矩形预处理。l[i][j]表示(i , j) 最大向上延伸的长度,其他同理。
mid[i][j] 表示这个点左右延申的最大长度。
用u[i][j]表示向上形成三角形的个数。 转移方程 u[i][j] = min(u[i - 1][j] + 1, mid[i][j] )
最后只需对每个点取min(u,d)即可。
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #include <assert.h> #define pb push_back #define INF 0x3F3F3F3F #define inf 1000000007 #define moD 1000000003 #define pii pair<int,int> #define eps 1e-6 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second typedef long long ll; typedef unsigned long long ull; const ll MOD = 1000000007; const int maxn = 2005; const double Inf = 10000.0; const double PI = acos(-1.0); using namespace std; ll mul(ll a, ll b, ll m) { ll res = 0; while (b) { if (b & 1) res = (res + a) % m; a = (a + a) % m; b >>= 1; } return res % m; } ll quickPower(ll a, ll b, ll m) { ll base = a; ll ans = 1ll; while (b) { if (b & 1) ans = mul(ans, base, m); base = mul(base, base, m); b >>= 1; } return ans; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); } ll Lcm(ll a, ll b) { return a / gcd(a, b) * b; } int readint() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } ll readll() { ll x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } ull readull() { ull x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } void Put(ll x) { if (x < 0) putchar('-'), x *= -1; if (x > 9) Put(x / 10); putchar(x % 10 + '0'); } char s[maxn][maxn]; int l[maxn][maxn],r[maxn][maxn]; int mid[maxn][maxn]; int n,m; int u[maxn][maxn],d[maxn][maxn]; int main(){ n = readint(), m = readint(); for(int i = 1; i <= n;i++) scanf("%s",s[i] + 1); for(int i = 1;i <= n;i++){ for(int j = 1;j <= m;j++) if(s[i][j] == s[i][j - 1]) l[i][j] = l[i][j - 1] + 1; else l[i][j] = 1; for(int j = m; j >= 1;j--) { if(s[i][j] == s[i][j + 1]) r[i][j] = r[i][j + 1] + 1; else r[i][j] = 1; mid[i][j] = min(l[i][j],r[i][j]); } } for(int i = 1;i <= m;i++){ for(int j = 1;j <= n;j++){ if(s[j][i] == s[j -1][i]) u[j][i] = min(mid[j][i],u[j - 1][i] + 1); else u[j][i] = 1; } for(int j = n;j >= 1;j--) { if(s[j][i] == s[j + 1][i]) d[j][i] = min(mid[j][i],d[j + 1][i] + 1); else d[j][i] = 1; } } int ans = 0; for(int i = 1; i <= n;i++) for(int j = 1;j <= m;j++) ans += min(u[i][j],d[i][j]); Put(ans); }