1. 程式人生 > >CF480E Parking Lot

CF480E Parking Lot

傳送門

題目翻譯給的很清楚w

這題官方給的演算法是分治,但是說實話我真的不知道它和分治有什麼關係……

有一個很正常的思路是先把所有修改都加上,之後先計算出來最小的情況(這個很簡單,dp一下即可),之後再逐步考慮修改有什麼影響。

首先如果一次修改對答案有影響的話,那麼更優的矩形一定是跨過這個障礙所在的一列的。如果當前的答案是ans的話,那麼我們相當於要統計,對於障礙所在的這一列,有沒有一個長為ans+1的區間,使得其每一行的左右兩端能拓展到ans+1.

這個好像和以前的矩形dp非常像……考慮用到懸線法,記錄每個點能向左右最遠拓展幾個格子。之後對於合法的正方形,我們只要在這一列從上向下,用單調佇列維護一下當前能拓展到的最遠左右距離是多少,把與當前行距離超過ans的都去掉,之後更新答案即可。

一開始像懸線法一樣處理一下左右拓展的距離,之後對於每一個修改暴力更新一下就好了。

看一下程式碼。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define
per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') #define fr friend inline #define y1 poj #define mp make_pair #define pr pair<int,int> #define fi first #define sc second #define pb push_back #define lowbit(x) x & (-x) using namespace std; typedef long long ll; const int
M = 2005; const int INF = 1000000009; const double eps = 1e-7; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct node { int x,y; }a[M]; int n,m,k,le[M][M],ri[M][M],q[M],dp[M][M],cur,ans[M],kx,ky,head,tail,tmp[M]; bool pd[M][M]; char s[M]; void init() { rep(i,1,n) rep(j,1,m) { if(pd[i][j]) dp[i][j] = 0; else dp[i][j] = min(dp[i-1][j-1],min(dp[i][j-1],dp[i-1][j])) + 1; cur = max(cur,dp[i][j]); } rep(i,1,n) rep(j,1,m) pd[i][j] ? le[i][j] = 0 : le[i][j] = le[i][j-1] + 1; rep(i,1,n) per(j,m,1) pd[i][j] ? ri[i][j] = 0 : ri[i][j] = ri[i][j+1] + 1; } bool check(int d) { head = 1,tail = 0; rep(i,1,n) { while(head <= tail && le[q[tail]][ky] >= le[i][ky]) tail--; q[++tail] = i; while(head <= tail && q[head] <= i - d) head++; tmp[i] = le[q[head]][ky]; } head = 1,tail = 0; rep(i,1,n) { while(head <= tail && ri[q[tail]][ky] >= ri[i][ky]) tail--; q[++tail] = i; while(head <= tail && q[head] <= i - d) head++; tmp[i] += ri[q[head]][ky] - 1; } rep(i,d,n) if(tmp[i] >= d) return 1; return 0; } int main() { n = read(),m = read(),k = read(); rep(i,1,n) { scanf("%s",s+1); rep(j,1,m) if(s[j] == 'X') pd[i][j] = 1; } rep(i,1,k) a[i].x = read(),a[i].y = read(),pd[a[i].x][a[i].y] = 1; init(); per(i,k-1,1) { ans[i+1] = cur; kx = a[i+1].x,ky = a[i+1].y,pd[kx][ky] = 0; rep(j,1,m) pd[kx][j] ? le[kx][j] = 0 : le[kx][j] = le[kx][j-1] + 1; per(j,m,1) pd[kx][j] ? ri[kx][j] = 0 : ri[kx][j] = ri[kx][j+1] + 1; while(check(cur+1)) cur++; } ans[1] = cur; rep(i,1,k) printf("%d\n",ans[i]); return 0; }
View Code