传送门 CF题粘的都是luogu题面因为有翻译qwq
恶意评分 实锤了
最优子矩阵问题++ 但是这把带修改不好做
最终复杂度要求是O(n^2) 考虑O(n)地处理一个修改带来的影响
自然想到l[i][j] r[i][j]存储左右拓展最远距离
然后发现向里面加点可能会改到很多行没法维护
所以我们正难则反就可以正常用l[][] r[][]
同时可以单调队列维护 开一个tmp[]存扩展最远距离然后逐步增大就行
判断增大一个一个加 反正答案<=n
这里用二维dp做了最开始的答案(后面都没有用dp)
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6 #include<iostream> 7 #define B puts("GGGGGGG"); 8 #define ms(a,b) memset(a,b,sizeof a) 9 #define rep(i,a,n) for(int i = a;i <= n;i++) 10 #define per(i,n,a) for(int i = n;i >= a;i--) 11 #define inf 2147483647 12 using namespace std; 13 typedef long long ll; 14 ll read() { 15 ll as = 0,fu = 1; 16 char c = getchar(); 17 while(c < '0' || c > '9') { 18 if(c == '-') fu = -1; 19 c = getchar(); 20 } 21 while(c >= '0' && c <= '9') { 22 as = as * 10 + c - '0'; 23 c = getchar(); 24 } 25 return as * fu; 26 } 27 const int N = 2003; 28 //head 29 struct node { 30 int x,y,res; 31 }ans[N]; 32 int dp[N][N],l[N][N],r[N][N]; 33 bool a[N][N]; 34 int n,m,k; 35 char s[N]; 36 int q[N],head,tail; 37 int tmp[N]; 38 bool checkans(int x,int y) { 39 head = 1,tail = 0; 40 ms(tmp,0); 41 rep(i,1,n) { 42 while(head <= tail && l[q[tail]][y] >= l[i][y]) tail--; 43 q[++tail] = i; 44 while(q[head] <= i - x) head++; 45 tmp[i] += l[q[head]][y]; 46 } 47 head = 1,tail = 0; 48 rep(i,1,n) { 49 while(head <= tail && r[q[tail]][y] >= r[i][y]) tail--; 50 q[++tail] = i; 51 while(q[head] <= i - x) head++; 52 tmp[i] += r[q[head]][y] - 1; 53 } 54 rep(i,x,n) if(tmp[i] >= x) return 1; 55 return 0; 56 } 57 58 void output() { 59 rep(i,1,n) { 60 rep(j,1,m) 61 printf("%d ",a[i][j]); 62 puts(""); 63 } 64 puts("-----------------"); 65 } 66 67 int main() { 68 n = read(),m = read(),k = read(); 69 rep(i,1,n) { 70 scanf("%s",s+1); 71 rep(j,1,m) a[i][j] = (s[j] == '.'); 72 } 73 // output(); 74 rep(i,1,k) { 75 ans[i].x = read(),ans[i].y = read(); 76 a[ans[i].x][ans[i].y] = 0; 77 } 78 // output(); 79 rep(i,1,n) per(j,m,1) { 80 if(!a[i][j]) continue; 81 if(i == 1 || j == m) { 82 dp[i][j] = 1; 83 ans[k].res = max(ans[k].res,1); 84 continue; 85 } 86 dp[i][j] = min(dp[i-1][j],dp[i][j+1]); 87 if(a[i-dp[i][j]][j+dp[i][j]]) dp[i][j]++; 88 ans[k].res = max(ans[k].res,dp[i][j]); 89 } 90 91 rep(i,1,n) rep(j,1,m) l[i][j] = a[i][j] * (l[i][j-1] + 1); 92 rep(i,1,n) per(j,m,1) r[i][j] = a[i][j] * (r[i][j+1] + 1); 93 int tmpp = ans[k].res; 94 per(i,k,2) { 95 ans[i].res = tmpp; 96 int x = ans[i].x,y = ans[i].y; 97 a[x][y] = 1; 98 // output(); 99 rep(j,1,m) l[x][j] = a[x][j] * (l[x][j-1] + 1); 100 per(j,m,1) r[x][j] = a[x][j] * (r[x][j+1] + 1); 101 while(checkans(tmpp+1,y)) tmpp++; 102 } 103 ans[1].res = tmpp; 104 rep(i,1,k) printf("%d ",ans[i].res); 105 return 0; 106 }