日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【2019牛客暑期多校训练营(第三场)- F】Planting Trees(单调队列,尺取)

發布時間:2023/12/10 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【2019牛客暑期多校训练营(第三场)- F】Planting Trees(单调队列,尺取) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:

鏈接:https://ac.nowcoder.com/acm/contest/883/F
來源:牛客網
?

The semester is finally over and the summer holiday is coming. However, as part of your university's graduation requirement, you have to take part in some social service during the holiday. Eventually, you decided to join a volunteer group which will plant trees in a mountain.

?

To simplify the problem, let's represent the mountain where trees are to be planted with an N×NN \times NN×N grid. Let's number the rows?1\ 1?1 to?N\ N?N from top to bottom, and number the columns?1\ 1?1 to?N\ N?N from left to right. The elevation of the cell in the?i\ i?i-th row and?j\ j?j-th column is denoted by ai,ja_{i,j}ai,j?. Your leader decides that trees should be planted in a rectangular area within the mountain and that the maximum difference in elevation among the cells in that rectangle should not exceed M. In other words, if the coordinates of the top-left and the bottom-right corners of the rectangle are (x1,y1)(x_1,y_1)(x1?,y1?) and (x2,y2)(x_2,y_2)(x2?,y2?), then the condition ∣ai,j?ak,l∣≤M|a_{i,j} - a_{k,l}| \le M∣ai,j??ak,l?∣≤M must hold for x1≤i,k≤x2,?y1≤j,l≤y2x_1 \le i,k \le x_2, \ y_1 \le j,l \le y_2x1?≤i,k≤x2?,?y1?≤j,l≤y2?. Please help your leader calculate the maximum possible number of cells in such a rectangle so that he'll know how many trees will be planted.

輸入描述:

The input contains multiple cases. The first line of the input contains a single integer T?(1≤T≤1000)T \ (1 \le T \le 1000)T?(1≤T≤1000), the number of cases. For each case, the first line of the input contains two integers N?(1≤N≤500)N\ (1 \le N \le 500)N?(1≤N≤500) and M?(0≤M≤105)M\ (0 \le M \le 10^5)M?(0≤M≤105). The following N lines each contain N integers, where the?j\ j?j-th integer in the?i\ i?i-th line denotes ai,j?(1≤ai,j≤105)a_{i,j} \ (1 \le a_{i,j} \le 10^5)ai,j??(1≤ai,j?≤105). It is guaranteed that the sum of N3N^3N3 over all cases does not exceed 25?10725 \cdot 10^725?107.

輸出描述:

For each case, print a single integer, the maximum number of cells in a valid rectangle.

示例1

輸入

復制

2 2 0 1 2 2 1 3 1 1 3 2 2 3 1 3 2 1

輸出

復制

1 4

題目大意:

給一個N*N矩陣(N<=500,且保證所有樣例的,時限3秒)

找出最大的矩陣滿足其中最大值和最小值的差小于等于M,讓你輸出的是這個可能的最大差值。

解題報告:

既然給你了N和時限這么清楚肯定就是讓你找一個N^3的做法而不能帶log。

首先枚舉兩行,然后剩下一個N用在求這一段中的最大最小值。

那么比較容易想到的就是二分長度然后拿個st表或者什么之類的掃一遍但是這樣肯定帶個log。

考慮尺取,這樣需要在O1時間內求出當前窗口的最大值和最小值的差,選擇單調隊列。

但是這題用STL會被卡,,所以手寫一波就OK了。

注意數組不是維護的前綴和,而是前綴最大值和前綴最小值。

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 500 + 5; int a[MAX][MAX],M,NUM[MAX],num[MAX]; int n; int ans; int qmin[555],qmax[555],f,b,F,B; int main() {int t;scanf("%d",&t);while(t--) {scanf("%d%d",&n,&M);ans=0;for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {scanf("%d",&a[i][j]);}}for(int u = 1; u<=n; u++) {for(int i = 1; i<=n; i++) num[i]=NUM[i]=a[u][i];for(int d = u; d<=n; d++) {for(int i = 1; i<=n; i++) num[i] = min(num[i],a[d][i]),NUM[i] = max(NUM[i],a[d][i]); // deque<int> qmin; deque<int> qmax;f=F=1;b=B=1;int i = 1, j = 1;while(i <= n) {if(i > j) j = i;while(j <= n) {while(f < b && num[qmin[b-1]] >= num[j]) b--;qmin[b++]=j;while(F < B && NUM[qmax[B-1]] <= NUM[j]) B--;qmax[B++]=j;if(NUM[qmax[F]] - num[qmin[f]] > M) break;j++;}if(qmin[f] == i) f++;if(qmax[F] == i) F++;ans = max(ans,(j-i)*(d-u+1));i++;}}}printf("%d\n",ans);}return 0 ; }

最近又重寫了一個優先移動右端點的版本:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 500 + 5; struct Deque {int a[MAX];int f,b;//f是隊首 b是隊尾Deque() {f=b=0;}void clear() {f=b=0;}bool empty() {return f==b;}void pop_back() {b--;}void pop_front(){f++;}void push_back(int x){a[b++] = x;}int back() {return a[b-1];}int front() {return a[f];} }Max,Min; int a[MAX][MAX],sum[MAX],SUM[MAX]; int n,M; int main() {int t;cin>>t;while(t--) {int ans = 0;Max.clear(),Min.clear();scanf("%d%d",&n,&M);for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) scanf("%d",&a[i][j]);}for(int up = 1; up<=n; up++) {for(int j = 1; j<=n; j++) sum[j] = SUM[j] = a[up][j];for(int down = up; down<=n; down++) {for(int j = 1; j<=n; j++) sum[j] = min(sum[j],a[down][j]),SUM[j] = max(SUM[j],a[down][j]);//預處理當前要用的sum和SUM數組int l = 1;Max.clear();Min.clear();for(int r = 1; r<=n; r++) {while(!Max.empty() && SUM[Max.back()] <= SUM[r]) Max.pop_back();Max.push_back(r);while(!Min.empty() && sum[Min.back()] >= sum[r]) Min.pop_back();Min.push_back(r);while(l<=r && SUM[Max.front()] - sum[Min.front()] > M) {if(Max.front() == l) Max.pop_front();if(Min.front() == l) Min.pop_front();l++;}ans = max(ans,(down-up+1) * (r-l+1));}}}printf("%d\n",ans);}return 0 ; }

?

總結

以上是生活随笔為你收集整理的【2019牛客暑期多校训练营(第三场)- F】Planting Trees(单调队列,尺取)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。