暴力枚举+单调队列优化dp——cf
stl的queue反而很慢
/* 枚举上下边界,再从左到右扫一次就ok */ #include<bits/stdc++.h> using namespace std; #define N 505 int n,m,sum[N][N],k; char s[N][N]; int main(){ freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); cin>>n>>m>>k; for(int i=1;i<=n;i++)scanf("%s",s[i]+1); //for(int i=1;i<=n;i++) // for(int j=1;j<=n;j++)s[i][j]='b'; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; if(s[i][j]=='a')sum[i][j]++; } if(k==0){puts("0");return 0;} int q[26][500]; long long ans=0; for(register int u=1;u<=n;u++) for(register int d=u+1;d<=n;d++){//枚举上下界 int head[26]={},tail[26]={}; int pos=1; for(register int i=1;i<=m;i++)if(s[u][i]==s[d][i]){//枚举每一列 while((sum[d][i]-sum[u-1][i])-(sum[d][pos-1]-sum[u-1][pos-1])>k) pos++; if(pos>i)continue; int now=s[u][i]-'a'; while(tail[now]-head[now]+1 && q[now][head[now]]<pos) head[now]++; ans+=tail[now]-head[now]+1; q[now][++tail[now]]=i; } } cout<<ans<<'\n'; }