2019暑假牛客第3场-F - Planting Trees-单调队列

题面:
2019暑假牛客第3场-F - Planting Trees-单调队列_第1张图片
2019暑假牛客第3场-F - Planting Trees-单调队列_第2张图片
题目传送门

题解:
2019暑假牛客第3场-F - Planting Trees-单调队列_第3张图片

#include
#define per(i,a,b) for(int i = (a);i <= (b);++i)
#define rep(i,a,b) for(int i = (a);i >= (b);--i)
#define INF 1e6
using namespace std;
const int maxn = 5e2 + 10;
int n = 0,m = 0;
int a[maxn][maxn];
void solve(){
	int mi[maxn],ma[maxn];
	int ans = 0;
	per(i,1,n){
		per(j,1,n){//对于每次枚举上边界,mi,ma数组都要初始化
			// mi[j] = INF; ma[j] = 0;
			mi[j] = ma[j] = a[i][j];
		}
		per(j,i,n){//枚举下边界
			per(k,1,n){//记录每列的最小值
				mi[k] = min(mi[k],a[j][k]); ma[k] = max(ma[k],a[j][k]);
			}
			// queue miq,maq;//存储最小值最大值的下标
			int miq[maxn],maq[maxn];
			int head1 = 1,head2 = 1,tail1 = 0,tail2 = 0; 
			if((j-i+1)*n <= ans){//剪枝优化
				continue;
			}
			int pos = 1;
			per(k,1,n){//枚举右边界
				while(head1 <= tail1 && mi[miq[tail1]] >= mi[k]){
					--tail1;
				}
				miq[++tail1] = k;
				while(head2 <= tail2 && ma[maq[tail2]] <= ma[k]){
					--tail2;
				}
				maq[++tail2] = k;
				//下面注释的代码也是可以的
				// while(pos <= k && ma[maq[head2]] - mi[miq[head1]] > m){
				// 	++pos;
				// 	while(head1 <= tail1 && miq[head1] < pos){
				// 		++head1;
				// 	}
				// 	while(head2 <= tail2 && maq[head2] < pos){
				// 		++head2;
				// 	}
				// }
				// if((j-i+1)*(n-pos+1) < ans){
				// 	break;
				// }
				// ans = max(ans,(j-i+1)*(k-pos+1));

				while(pos <= k){
					if((j-i+1)*(k-pos+1) < ans){//剪枝优化
						break;
					}
					if(pos <= miq[head1] && pos <= maq[head2]){
						if(ma[maq[head2]] - mi[miq[head1]] <= m){
							ans = max(ans,(j-i+1)*(k-pos+1));
							break;
						}else{
							if(miq[head1] < maq[head2]){
								pos = miq[head1] + 1;
								++head1;
							}else if(miq[head1] > maq[head2]){
								pos = maq[head2] + 1;
								++head2;
							}else{
								pos = miq[head1] + 1;
								++head1; ++head2;
							}
						}
					}else{
						while(head1 <= tail1 && pos > miq[head1]){
							++head1;
						}
						while(head2 <= tail2 && pos > maq[head2]){
							++head2;
						}
					}
				}
			}
		}
	}
	printf("%d\n",ans);
}
int main(){
	// queue qu;
	// qu.push(1);
	// qu.push(2);
	// qu.push(3);
	// printf("%d %d\n",qu.front(),qu.back());
	int T = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);
		per(i,1,n){
			per(j,1,n){
				scanf("%d",&a[i][j]);
			}
		}
		solve();
	}

	return 0;
}

你可能感兴趣的:(牛客,单调栈)