2019牛客暑期多校训练营(第三场)F. Planting Trees
题目大意:给出一个N*N的方阵,每个点有高度,圈出一个面积尽可能大的矩形满足(最大高度-最小高度)<=M.
思路:单调队列+枚举。枚举上下边界,对于固定上下边界枚举右端点,对于每个右端点求出最左端的满足条件的位置,计算矩形面积。用两个数组维护每一列(上边界到下边界)的最大最小值,通过两个单调队列维护单调递增和单调递减的下标(右端点右移时改变队尾)。
链接:https://ac.nowcoder.com/acm/contest/883/F
#include<bits/stdc++.h> #define ll long long using namespace std; int n,m; struct edge{ ll p,l,r,maxv,minv; }; const int N=505; int maxa[N]; int mina[N]; int a[N][N]; const ll INF=1e9+7; #define pii pair<int,int> int main(){ int t;cin>>t; while(t--){ cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin>>a[i][j]; } } ll ans=0; for(int up=1;up<=n;up++){ for(int i=1;i<=n;i++){ maxa[i]=0; mina[i]=INF; } for(int down=up;down<=n;down++){ for(int i=1;i<=n;i++){ maxa[i]=max(maxa[i],a[down][i]); mina[i]=min(mina[i],a[down][i]); } deque<pii>q1,q2; int l=1; for(int i=1;i<=n;i++){ //cout<<maxa[i]<<endl; //cout<<mina[i]<<endl; while(!q1.empty()&&q1.back().second<maxa[i])q1.pop_back(); q1.push_back(make_pair(i,maxa[i])); while(!q2.empty()&&q2.back().second>mina[i])q2.pop_back(); q2.push_back(make_pair(i,mina[i])); while(!q1.empty()&&!q2.empty()&&q1.front().second-q2.front().second>m){ if(q1.front().first<=q2.front().first){ l=q1.front().second+1; q1.pop_front(); //if(!q1.empty())l=max(l,q1.front().first); //if(!q2.empty())l=max(l,q2.front().first); }else{ l=q2.front().second+1; q2.pop_front(); //if(!q1.empty())l=max(l,q1.front().first); //if(!q2.empty())l=max(l,q2.front().first); } } if(!q1.empty()&&!q2.empty()){ //cout<<q1.front().second<<' '<<q2.front().second<<' '<<q1.front().first<<' '<<q2.front().first<<endl; //cout<<"U D"<<up<<' '<<down<<endl; //cout<<"L R:"<<l<<' '<<i<<endl; ans=max(ans,1ll*(i-l+1)*(down-up+1)); } } } } cout<<ans<<"\n"; } return 0; }

浙公网安备 33010602011771号