问你1000*1000的字母矩阵中,有多少个行列中均无相同元素的.
用尺取预处理出每个元素向右走多少一路上没有重复,向下走一路上没有重复.
枚举左上端点,然后扫一遍第一行,然后用类似打标记的方法,找到接下来的每一行,最长可以延伸多少,然后在扫一遍每一行,看他到底能够延伸多长(min)
#include <iostream>
#include <vector>
#include <set>
#define debug(x) //std::cerr << #x << " = " << (x) << std::endl
using namespace std;
typedef long long LL;
const int MAXN = 1e3 + 17;
const int MOD = 998244353;
int mp[MAXN][MAXN];
int rg[MAXN][MAXN],down[MAXN][MAXN];
int main()
{
#ifdef noob
freopen("Input.txt", "r", stdin);
freopen("Output.txt", "w", stdout);
#endif
LL n,m,ans = 0;
cin>>n>>m;
for (int i = 0; i < n; ++i)
{
string str;
cin>>str;
for (int j = 0; j < m; ++j)
{
if(str[j]>='a')
mp[i][j] = str[j]-'a';
else
mp[i][j] = str[j]-'A'+26;
rg[i][j] = m-j-1;
down[i][j] = n-i-1;
}
}
for (int i = 0; i < n; ++i)
{
int l = 0,r = 0;
set<int > s;
while(r<m)
{
if(s.find(mp[i][r])==s.end())
{
s.insert(mp[i][r]);
r++;
}
else
{
rg[i][l] = r-l-1;
s.erase(mp[i][l]);
l++;
}
}
}
for (int j = 0; j < m; ++j)
{
int l = 0,r = 0;
set<int > s;
while(r<n)
{
if(s.find(mp[r][j])==s.end())
{
s.insert(mp[r][j]);
r++;
}
else
{
down[l][j] = r-l-1;
s.erase(mp[l][j]);
l++;
}
}
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
vector<int > mx(60,0),flag(60,0);
int sum = 0,mn = 100;
for (int p = 0; p <= rg[i][j]; ++p)
{
int x = p+j;
flag[min(mn,down[i][x])]++;
mn = min(mn,down[i][x]);
sum++;
}
for (int k = 0; sum&&k < 60; ++k)
{
mx[k] = sum;
sum -= flag[k];
}
int mnx = 100;
for (int p = 0; p < 60; ++p)
{
int x = p+i;
if(x>=n) break;
ans += min(mnx,min(rg[x][j]+1,mx[p]));
mnx = min(mnx,min(rg[x][j]+1,mx[p]));
}
}
}
cout<<ans<<endl;
return 0;
}
事实上只要有了52*52*nm的算法,就可以容易的想出这种新做法,但是我想了很久才想出来52*52的..这题很好,但是我真的不会,别人的题解叶看不懂,T^T