双指针优化二维前缀和
先看例题https://www.luogu.com.cn/problem/P8783
由题意可以快速写出一个\(n^4\)复杂度的二维前缀和,如下
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int x=i;x<=n;x++){
for(int y=j;y<=m;y++){
int t=(pre[x][y]-pre[x][j-1]-pre[i-1][y]+pre[i-1][j-1]);
if(t<=k){
ans++;
}
}
}
}
}
但是根据题目中\(n \le 500\)的范围来看,显然是无法拿满分的,因此可以换一种枚举思路,即利用双指针维护一个矩阵的左上点与右下点,当某一个范围内的答案再也无法满足题意时统计答案,可以将时间复杂度优化到接近\(O(n^3)\)
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
//(i,l)可以视为左上角点,(j,r)为右下角点
for(int l=1,r=1;r<=m;r++){
while(l<=r and pre[j][r]-pre[i-1][r]-pre[j][l-1]+pre[i-1][l-1]>k) l++; // 枚举右下角点
ans+=(r-l+1);
}
}
}
浙公网安备 33010602011771号